开发者

What does the function declaration "sub function($$)" mean?

开发者 https://www.devze.com 2022-12-24 15:53 出处:网络
I have been using Perl for some time, but today I开发者_开发技巧 came across this code: sub function1($$)

I have been using Perl for some time, but today I开发者_开发技巧 came across this code:

sub function1($$)
{
   //snip
}

What does this mean in Perl?


It is a function with a prototype that takes two scalar arguments.


There are strong arguments for not actually using Perl prototypes in general - as noted in the comments below. The strongest argument is probably:

  • Far More Than Everything You've Ever Wanted to Know about Prototypes in Perl

There's a discussion on StackOverflow from 2008:

  • SO 297034

There's a possible replacement in the MooseX::Method::Signatures module.


As the other answer mentions, the $$ declares a prototype. What the other answer doesn't say is what prototypes are for. They are not for input validation, they are hints for the parser.

Imagine you have two functions declared like:

sub foo($)  { ... }
sub bar($$) { ... }

Now when you write something ambiguous, like:

foo bar 1, 2

Perl knows where to put the parens; bar takes two args, so it consumes the two closest to it. foo takes one arg, so it takes the result of bar and the two args:

foo(bar(1,2))

Another example:

bar foo 2, 3

The same applies; foo takes one arg, so it gets the 2. bar takes two args, so it gets foo(2) and 3:

bar(foo(2),3)

This is a pretty important part of Perl, so dismissing it as "never use" is doing you a disservice. Nearly every internal function uses prototypes, so by understanding how they work in your own code, you can get a better understanding of how they're used by the builtins. Then you can avoid unnecessary parentheses, which makes for more pleasant-looking code.

Finally, one anti-pattern I will warn you against:

package Class;
sub new ($$) { bless $_[1] }
sub method ($) { $_[0]->{whatever} }

When you are calling code as methods (Class->method or $instance->method), the prototype check is completely meaningless. If your code can only be called as a method, adding a prototype is wrong. I have seen some popular modules that do this (hello, XML::Compile), but it's wrong, so don't do it. If you want to document how many args to pass, how about:

sub foo {
    my ($self, $a, $b) = @_; # $a and $b are the bars to fooify
    ....

or

use MooseX::Method::Signatures;

method foo(Bar $a, Bar $b) { # fooify the bars
    ....

Unlike foo($$), these are meaningful and readable.

0

精彩评论

暂无评论...
验证码 换一张
取 消