What does the function declaration “sub function($$)” mean?

前端 未结 2 1519
没有蜡笔的小新
没有蜡笔的小新 2020-11-29 12:24

I have been using Perl for some time, but today I came across this code:

sub function1($$)
{
   //snip
}

What does this mean in Perl?

相关标签:
2条回答
  • 2020-11-29 13:16

    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.

    0 讨论(0)
  • 2020-11-29 13:16

    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 讨论(0)
提交回复
热议问题