Why is parenthesis optional only after sub declaration?

后端 未结 4 1117
栀梦
栀梦 2020-12-05 23:40

(Assume use strict; use warnings; throughout this question.)

I am exploring the usage of sub.

sub bb { print @_; }         


        
相关标签:
4条回答
  • 2020-12-05 23:46

    The best answer I can come up with is that's the way Perl is written. It's not a satisfying answer, but in the end, it's the truth. Perl 6 (if it ever comes out) won't have this limitation.

    Perl has a lot of crud and cruft from five different versions of the language. Perl 4 and Perl 5 did some major changes which can cause problems with earlier programs written in a free flowing manner.

    Because of the long history, and the various ways Perl has and can work, it can be difficult for Perl to understand what's going on. When you have this:

    b $a, $c;
    

    Perl has no way of knowing if b is a string and is simply a bareword (which was allowed in Perl 4) or if b is a function. If b is a function, it should be stored in the symbol table as the rest of the program is parsed. If b isn't a subroutine, you shouldn't put it in the symbol table.

    When the Perl compiler sees this:

    b($a, $c);
    

    It doesn't know what the function b does, but it at least knows it's a function and can store it in the symbol table waiting for the definition to come later.

    When you pre-declare your function, Perl can see this:

    sub b;   #Or use subs qw(b); will also work.
    
    b $a, $c;
    

    and know that b is a function. It might not know what the function does, but there's now a symbol table entry for b as a function.

    One of the reasons for Perl 6 is to remove much of the baggage left from the older versions of Perl and to remove strange things like this.

    By the way, never ever use Perl Prototypes to get around this limitation. Use use subs or predeclare a blank subroutine. Don't use prototypes.

    0 讨论(0)
  • 2020-12-05 23:56

    I think what you are missing is that Perl uses a strictly one-pass parser. It does not scan the file for subroutines, and then go back and compile the rest. Knowing this, the following describes how the one pass parse system works:

    In Perl, the sub NAME syntax for declaring a subroutine is equivalent to the following:

    sub name {...}   ===   BEGIN {*name = sub {...}}
    

    This means that the sub NAME syntax has a compile time effect. When Perl is parsing source code, it is working with a current set of declarations. By default, the set is the builtin functions. Since Perl already knows about these, it lets you omit the parenthesis.

    As soon as the compiler hits a BEGIN block, it compiles the inside of the block using the current rule set, and then immediately executes the block. If anything in that block changes the rule set (such as adding a subroutine to the current namespace), those new rules will be in effect for the remainder of the parse.

    Without a predeclared rule, an identifier will be interpreted as follows:

    bareword       ===   'bareword'   # a string
    bareword LIST  ===   syntax error, missing ','
    bareword()     ===   &bareword()  # runtime execution of &bareword
    &bareword      ===   &bareword    # same
    &bareword()    ===   &bareword()  # same
    

    When using strict and warnings as you have stated, barewords will not be converted into strings, so the first example is a syntax error.

    When predeclared with any of the following:

    sub bareword;
    use subs 'bareword';
    sub bareword {...}
    BEGIN {*bareword = sub {...}}
    

    Then the identifier will be interpreted as follows:

    bareword      ===   &bareword()     # compile time binding to &bareword
    bareword LIST ===   &bareword(LIST) # same
    bareword()    ===   &bareword()     # same
    &bareword     ===   &bareword       # same
    &bareword()   ===   &bareword()     # same
    

    So in order for the first example to not be a syntax error, one of the preceding subroutine declarations must be seen first.

    As to the why behind all of this, Perl has a lot of legacy. One of the goals in developing Perl was complete backwards compatibility. A script that works in Perl 1 still works in Perl 5. Because of this, it is not possible to change the rules surrounding bareword parsing.

    That said, you will be hard pressed to find a language that is more flexible in the ways it lets you call subroutines. This allows you to find the method that works best for you. In my own code, if I need to call a subroutine before it has been declared, I usually use name(...), but if that subroutine has a prototype, I will call it as &name(...) (and you will get a warning "subroutine called too early to check prototype" if you don't call it this way).

    0 讨论(0)
  • 2020-12-06 00:08

    The reason is that Larry Wall is a linguist, not a computer scientist.

    Computer scientist: The grammar of the language should be as simple & clear as possible.

    • Avoids complexity in the compiler
    • Eliminates sources of ambiguity

    Larry Wall: People work differently from compilers. The language should serve the programmer, not the compiler. See also Larry Wall's outline of the three virtues of a programmer.

    0 讨论(0)
  • 2020-12-06 00:09

    Parentheses are optional only if the subroutine has been predeclared. This is documented in perlsub.

    Perl needs to know at compile time whether the bareword is a subroutine name or a string literal. If you use parentheses, Perl will guess that it's a subroutine name. Otherwise you need to provide this information beforehand (e.g. using subs).

    0 讨论(0)
提交回复
热议问题