简体   繁体   中英

Perl - Differences in BEGIN an non-BEGIN block

I have a question regarding the const declaration in perl, and could not figure out the differences, please kindly point out what are the differences.

Below is the code:

BEGIN {
  *SIZE = sub() { 2 };
}  
*ITEM = sub() { 10 };

print 'size=', SIZE, "\n";
print 'item=', &ITEM, "\n";

Now is the question, Why

  print 'item=', &ITEM, "\n";

line must have a '&' in front of ITEM, But

  print 'size=', SIZE, "\n";   

line do not need to have a '&' in front of SIZE.

And I know the BEGIN block is run at compile time.

Because the BEGIN block is run at compile time, the compiler knows about the assignment to *SIZE , while the assignment to *ITEM hasn't happened yet.

Because the compiler doesn't know about *ITEM , calls to ITEM are ambiguous, thus you must prefix it with an & . Otherwise, the compiler thinks it could be a "bare word" -- an unquoted string.

If you use strict , the compile will assume that bare words are functions.

use constant may also be a better way to declare constants, rather than doing it manually.

The code

BEGIN {
  *SIZE = sub() { 2 };
}  
*ITEM = sub() { 10 };

print 'size=', SIZE, "\n";
print 'item=', ITEM, "\n";

would get processed as follows if there was no error:

  • Compile file.
    • Compile BEGIN block.
      • *SIZE = sub() { 2 };
    • Execute BEGIN block.
      • *SIZE = sub() { 2 };
    • Compile *ITEM = sub() { 10 };
    • Compile print 'size=', SIZE, "\\n";
    • Compile print 'item=', ITEM, "\\n";
  • Execute file.
    • Execute *ITEM = sub() { 10 };
    • Execute print 'size=', SIZE, "\\n";
    • Execute print 'item=', ITEM, "\\n";

Note how print 'item=', ITEM, "\\n"; is compiled before the sub exists. If ITEM existed as a sub, that would be allowed. But ITEM doesn't exist as a sub. In the absence of any other meaning, identifiers are bare words, and bare words are compiled into a string with the same value.

>perl -E"my $x = ITEM; say $x;"
ITEM

>perl -E"my $x = 'ITEM'; say $x;"
ITEM

That is, unless you specifically ask Perl to do otherwise:

>perl -E"use strict; my $x = ITEM; say $x;"
Bareword "ITEM" not allowed while "strict subs" in use at -e line 1.
Execution of -e aborted due to compilation errors.

That means you need to make ITEM look like a sub call.

print 'item=', ITEM(), "\n";

&ITEM also works, since & is the instruction to tell Perl to ignore prototypes.

The & prefix unambiguously means "this is a user-defined subroutine call coming up next". You can omit it when you are using parens after your function name and your function name doesn't conflict with a built-in, or if you've declared/defined your function before you use it and the name doesn't conflict with a built-in.

Continuing read here

And check @Sean McMillan response.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM