10

Unquoted words seem to have a great many meanings in Perl.

print STDERR $msg;

$hash{key}

func( param => $arg )

my $x = str;

How does one determine the meaning of these?

ikegami
  • 367,544
  • 15
  • 269
  • 518

1 Answers1

16

The following chart shows how Perl resolves identifiers in order of descending priority.

It also applies to identifiers chained by :: (which I'll call "qualified identifiers") unless otherwise stated.

  1. Syntactically-defined meaning, when syntactically expected.

     sub foo { }          # «foo» («sub» is covered later)
     sub main::foo { }    # «main::foo» («sub» is covered later)
     method Class         # «Class» («method» is covered later)
     method Some::Class   # «Some::Class» («method» is covered later)
     $foo
     $main::foo
     //i
     =head
     <<FOO
     Class::
     Some::Class::
     LABEL:
    
  2. String literal, when followed by a => or when the entirety of a hash index expression.

    This doesn't apply to qualified identifiers.

     my %h = ( a => 1 );
     $h{a}
    
  3. Variable name, when the entirety of the dereference expression.

     ${foo}
     ${main::foo}
    

    Note that using the name of a keyword, named operator or declared sub will result in an ambiguous use warning.

  4. Keyword.

     while (1) { }
     sub { }
     use
     __END__
    
  5. Sub call, when the name of a previously imported sub.

     use Time::HiRes qw( time );
     time
     main::time
    
  6. Invocation of a named list operator, named unary operator or named nullary operator.

     print $x, $y, $z;
     $c = chr $i;
     $t = time;
     $t = CORE::time;
    
  7. Label, when used as the operand for next, last, redo or goto.

    A qualified identifier treated as a label results in a compilation error since labels can't be qualified identifiers.

     next LABEL;
    
  8. Sub call or inlined constant, when the name of a previously declared sub or constant.

     sub foo { }
     foo                          # Calls sub «foo»
     main::foo                    # Calls sub «foo»
    
     sub bar;
     bar                          # Calls sub «bar»
    
     use constant FOO => 123;
     FOO                          # Replaced with the value of the constant.
    
  9. Indirect method call, when followed by a possibly-qualified identifier, a possibly-qualified identifier suffixed with ::, a scalar (incl array element or hash element) or a block.

     method Class           # Calls method «method» («Class» is covered earlier)
     method Some::Class     # Calls method «method» («Some::Class» is covered earlier)
     method Class::         # Calls method «method» («Class» is covered earlier)
     method Some::Class::   # Calls method «method» («Some::Class» is covered earlier)
     method $o              # Calls method «method»
     method { $o }          # Calls method «method»
    
     Base::method Class     # Calls method «Base::method» («Class» is covered earlier)
    

    You can use the no indirect pragma to warn when code is parsed this way.

  10. Glob, when used as the operand for an operator expecting a file handle.

     open(FH, '>', $qfn) or die $!;      # Equivalent to open(*FH, ...) or ...;
     print FH "Hello, World!\n";         # Equivalent to print *FH ...;
     print main::FH "Hello, World!\n";   # Equivalent to print *main::FH ...;
    
  11. String literal, in the following situations:

    • When used as the invocant of a direct method call.

        Class->method(@args)         # Uses the string «Class» as the invocant.
        Some::Class->method(@args)   # Uses the string «Some::Class» as the invocant.
      
    • When used as the operand for unary minus.

        -foo
        -foo::bar
      
    • When used as an argument for the a sub parameter with a prototype of *.

        sub myprint(*@);
        myprint(FH, "Hello, World\n");
        myprint(main::FH, "Hello, World\n");
      
  12. String literal. This is disallowed by use strict qw( subs );.

Hopefully, I didn't miss any.

Thanks to @mosvy, @Grinnz and @stevesliva! Each has uncovered a few cases I had missed.


CURRENTLY MISSING:

  • funcname in sort funcname.

  • BEGIN and similar. They sometimes act as keyword, and sometimes as a declared sub.

  • Importing a sub named print doesn't follow the above steps.

    $ perl -M5.010 -e'
       use subs qw( time );
       eval { time; };
       say $@ =~ /Undefined sub/ ? "ok" : "bad";
    '
    ok
    
    $ perl -M5.010 -e'
       use subs qw( system );
       eval { system; };
       say $@ =~ /Undefined sub/ ? "ok" : "bad";
    '
    ok
    
    $ perl -M5.010 -e'
       use subs qw( print );
       eval { print; };
       say $@ =~ /Undefined sub/ ? "ok" : "bad";
    '
    bad
    

    I don't know what makes that one special, and I don't know if there are others or not. I was guessing it's because print doesn't have a prototype, but system has no prototype either.

ikegami
  • 367,544
  • 15
  • 269
  • 518
  • I have a strong feeling of deja-vu, but haven't you forgot the `package method args` sytax? `use strict; sub bar::foo {} foo bar foo bar`. And no, it's not the same as `print STDOUT`, because `print(STDOUT "foo\n")` works, but not `method(PKG "foo\n")` in general. –  Oct 07 '19 at 10:47
  • @mosvy That is [indirect object syntax](https://perldoc.pl/perlobj#Indirect-Object-Syntax) and it's actually `method package args`. As a corollary, some builtins like print/say and system/exec that take a first argument without a comma pretend to use indirect object syntax but are actually a parser special case. – Grinnz Oct 07 '19 at 15:03
  • I would also add there are some other special cases like the first argument of `sort` which takes a bareword as a sub name regardless of strict 'subs'. – Grinnz Oct 07 '19 at 15:05
  • @Grinnz my bad, I reversed them in the verbiage but the examples's OK ;-) –  Oct 07 '19 at 15:57
  • @mosvy, Both direct (`Class->method`) and indirect (`method Class`) are missing. I'll fix. (Yeah, I've posted this before, but it was in a footnote to a tangentially-related question, and I found myself wanting to link to it.) – ikegami Oct 07 '19 at 16:26
  • @Grinnz `print` is covered ("Glob, when used as the operand for an operator expecting a file handle.") I'll add `sort`'s operand. – ikegami Oct 07 '19 at 16:27
  • There's also the `${foo}` way of writing `$foo` (which is normally used in double-quote string literals, but works outside of them too). I'll add that too. – ikegami Oct 07 '19 at 16:30
  • @ikegami Another special case that you might consider, the unary `-` applied to a bareword will stringify it. – Grinnz Oct 07 '19 at 17:17
  • @Grinnz, yup, definitely a separate case. If it was just a bareword being "negated" (just like how the value of `$x` is "negated" in `perl -e'use strict; my $x = "foo"; CORE::say -$x'`), then the following would fail with a strict error: `perl -e'use strict; my $x = -foo'`. I'm working on something else right now, but I'll update the answer later today or tomorrow. It requires a lot of testing to find out where everything falls! – ikegami Oct 07 '19 at 17:22
  • @stevesliva, I think the `FOO` of `< – ikegami Oct 07 '19 at 18:39
  • @ikegami - `here-doc` and `perlpod` (yes, `=head1` or `__END__` first) are just two situations where I've found myself looking at what appear to be a bunch of barewords... which I suppose are simply specially quoted multiline strings. Perhaps also the *phase* barewords like `BEGIN` and `END`, and maybe *label* words? – stevesliva Oct 07 '19 at 19:12
  • @stevesliva, `BEGIN { }` is just like `while (1) { }`, I can add it as an example. – ikegami Oct 07 '19 at 19:14
  • @stevesliva, `FOO:` is a good one. I'll add both `FOO:` and `next FOO`. // Re ""*true bareword*", Not by Perl's definition. "*A word that has no other interpretation in the grammar will be treated as if it were a quoted string. These are known as "barewords".*" And they are outlawed by `use strict qw( subs );`. `next FOO` falls into the "has other interpretation" category – ikegami Oct 07 '19 at 20:08
  • @stevesliva, I suspect that `__END__` is no different than other keywords, but I'll double-check. – ikegami Oct 07 '19 at 20:14
  • Note that BEGIN can also be written `sub BEGIN`, though it's not a regular subroutine. `END` and `__END__` are different (the former is akin to BEGIN, the latter is a special token similar to `__DATA__` that causes parsing to end) – Grinnz Oct 07 '19 at 21:16
  • @Grinnz, `sub BEGIN { }` is syntactically no different than an ordinary sub decleration, so that's not relevant here. /// I know what `__END__` does :) Even if it has a compile-time effect, that doesn't make it special here. `use` and `my` also have compile-time effects, for example. – ikegami Oct 07 '19 at 21:20
  • @mosvy I've updated the answer in response to your comments. – ikegami Nov 03 '19 at 15:24
  • @Grinnz I've updated the answer in response to your comments. altough I haven't incorporated `sort funcname LIST` yet. I'm apprehensive about touching that! – ikegami Nov 03 '19 at 15:24
  • @stevesliva I've updated the answer in response to your comments. Turns out that labels were really interesting. `goto time;` tries to jump to `1572794637`, but `goto some_sub;` tries to jump to `some_sub`. – ikegami Nov 03 '19 at 15:24
  • That's bizarre. `goto eval 'some_sub'` works but `goto some_sub` abends `Can't find label some_sub` – stevesliva Nov 04 '19 at 14:02
  • 1
    @stevesliva Yeah, that's what I was saying. `eval` in `goto eval 'some_sub'` is taken as a operator (#6), but `some_sub` in `goto some_sub` is taken as a label (#7), not a sub call (#9). – ikegami Nov 04 '19 at 21:22