By Alnitak

2008-11-17 21:37:57 8 Comments

In another Stack Overflow question Leon Timmermans asserted:

I would advice you not to use prototypes. They have their uses, but not for most cases and definitely not in this one.

Why might this be true (or otherwise)? I almost always supply prototypes for my Perl functions, and I've never before seen anyone else say anything bad about using them.


@brian d foy 2016-04-24 15:29:46

Some people, looking at a Perl subroutine prototype, thinks it means something that it doesn't:

sub some_sub ($$) { ... }

To Perl, that means that the parser expects two arguments. It's Perl's way of letting you create subroutines that behave like built-ins, all of which know what to expect from the succeeding code. You can read about prototypes in perlsub

Without reading the documentation, people guess that the prototypes refer to run time argument checking or something similar that they've seen in other languages. As with most things people guess about Perl, they turn out to be wrong.

However, starting with Perl v5.20, Perl has a feature, experimental as I write this, that gives something more like what users expect and what. Perl's subroutine signatures does run time argument counting, variable assigning, and default setting:

use v5.20;
use feature qw(signatures);
no warnings qw(experimental::signatures);

animals( 'Buster', 'Nikki', 'Godzilla' );

sub animals ($cat, $dog, $lizard = 'Default reptile') { 
    say "The cat is $cat";
    say "The dog is $dog";
    say "The lizard is $lizard";

This is the feature you probably want if you're considering prototypes.

@Michael Carman 2008-11-17 22:54:09

Prototypes aren't bad if used correctly. The difficulty is that Perl's prototypes don't work the way people often expect them to. People with a background in other programming languages tend to expect prototypes to provide a mechanism for checking that function calls are correct: that is, that they have the right number and type of arguments. Perl's prototypes are not well-suited for this task. It's the misuse that's bad. Perl's prototypes have a singular and very different purpose:

Prototypes allow you to define functions that behave like built-in functions.

  • Parentheses are optional.
  • Context is imposed on the arguments.

For example, you could define a function like this:

sub mypush(\@@) { ... }

and call it as

mypush @array, 1, 2, 3;

without needing to write the \ to take a reference to the array.

In a nutshell, prototypes let you create your own syntactic sugar. For example the Moose framework uses them to emulate a more typical OO syntax.

This is very useful but prototypes are very limited:

  • They have to be visible at compile-time.
  • They can be bypassed.
  • Propagating context to arguments can cause unexpected behavior.
  • They can make it difficult to call functions using anything other than the strictly prescribed form.

See Prototypes in perlsub for all the gory details.

@Alnitak 2008-11-18 19:53:50

I've accepted this answer because I feel it best answers the question - prototypes aren't intrinsically bad, it's just how you use them.

@Kent Fredric 2009-05-18 22:50:12

Moose prototypes on the otherhand, are /awesome/

@Peter Mortensen 2016-04-24 09:58:17

So they are a misnomer, then?

@cjm 2008-11-17 21:55:27

The problem is that Perl's function prototypes don't do what people think they do. Their purpose is to allow you to write functions that will be parsed like Perl's built-in functions.

First of all, method calls completely ignore prototypes. If you're doing OO programming, it doesn't matter what prototype your methods have. (So they shouldn't have any prototype.)

Second, prototypes aren't strictly enforced. If you call a subroutine with &function(...), the prototype is ignored. So they don't really provide any type safety.

Third, they're spooky action-at-a-distance. (Especially the $ prototype, which causes the corresponding parameter to be evaluated in scalar context, instead of the default list context.)

In particular, they make it hard to pass parameters from arrays. For example:

my @array = qw(a b c);

foo($array[0], $array[1], $array[2]);

sub foo ($;$$) { print "@_\n" }

foo($array[0], $array[1], $array[2]);


a b c
a b
a b c
a b c

along with 3 warnings about main::foo() called too early to check prototype (if warnings are enabled). The problem is that an array (or array slice) evaluated in scalar context returns the length of the array.

If you need to write a function that acts like a built-in, use a prototype. Otherwise, don't use prototypes.

Note: Perl 6 will have completely revamped and very useful prototypes. This answer applies only to Perl 5.

@Paul Tomblin 2008-11-17 21:57:48

But they still provide a useful check that your caller and the sub are using the same number of arguments, so what's wrong with that?

@Alnitak 2008-11-17 22:02:31

that's sort of the point of my question - I never use the old &func syntax, so the prototype does provide useful function parameter checking.

@Jonathan Leffler 2008-11-17 22:05:46

No; the general consensus is that Perl function prototypes provide essentially no benefit. You may as well not bother with them, at least in Perl 5. Perl 6 might be a different (better) story.

@friedo 2008-11-17 22:22:44

There are better ways to validate arguments, such as the Params::Validate module:…

@pilcrow 2012-05-09 23:06:19

Correction: array slicing returns a list, so an array slice in a scalar context returns the final element of the list. Your second-to-last invocation of foo() prints 2 because that is the final element in your two element slice. Change to my @array = qw(foo bar baz) and you'll see the difference. (As an aside, this is why I don't initialize arrays/lists to 0- or 1-based numeric sequences in throw-away, demonstrative code. Confusion between indices, counts, and elements in contexts has bitten me more than once. Silly but true.)

@Flimm 2014-11-20 15:11:58

@pilcrow: I edited the answer to use a b c to make your point clearer.

@Leon Timmermans 2008-11-18 17:26:45

I agree with the above two posters. In general, using $ should be avoided. Prototypes are only useful when using block arguments (&), globs (*), or reference prototypes (\@, \$, \%, \*)

@The Sidhekin 2015-09-09 21:47:10

In general, perhaps, but I'd like to mention two exceptions: First, the ($) prototype creates a named unary operator, which can be useful (certainly Perl finds them useful; I have too, on occasion). Second, when overriding built-ins (whether through import or using CORE::GLOBAL::), you should in general stick to whatever prototype the built-in had, even if that includes a $, or you might surprise the programmer (yourself, even) with list context where the built-in would otherwise provide scalar context.

Related Questions

Sponsored Content

27 Answered Questions

7 Answered Questions

[SOLVED] Why does modern Perl avoid UTF-8 by default?

  • 2011-05-28 15:12:36
  • w.k
  • 100968 View
  • 561 Score
  • 7 Answer
  • Tags:   perl unicode utf-8

34 Answered Questions

[SOLVED] What's the difference between a method and a function?

39 Answered Questions

[SOLVED] var functionName = function() {} vs function functionName() {}

29 Answered Questions

[SOLVED] __proto__ VS. prototype in JavaScript

9 Answered Questions

[SOLVED] What does the exclamation mark do before the function?

  • 2010-09-20 21:21:51
  • Sebastian Otto
  • 169703 View
  • 1254 Score
  • 9 Answer
  • Tags:   javascript function

38 Answered Questions

[SOLVED] How to fix a locale setting warning from Perl?

  • 2010-03-23 12:27:18
  • xain
  • 529337 View
  • 599 Score
  • 38 Answer
  • Tags:   perl locale

14 Answered Questions

[SOLVED] Use of 'prototype' vs. 'this' in JavaScript?

Sponsored Content