Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is this anon subroutine declaration parsed as an indirect object method in Perl?

In the following anonymous subroutine declaration, Perl seems to be parsing it as an indirect method call, rather than as a subroutine:

use 5.010;
use strict;
use warnings;

sub proxy {
    my $new = shift;
    say "creating proxy: $new";
    sub :lvalue {
        say "running proxy: $new";
        tie my $ret, 'Some::Package', shift, $new;
        $ret
    }
}

say "before";
my $p1 = proxy '_value';
say "p1 declared: $p1";
my $p2 = proxy 'value';
say "p2 declared: $p2";

which prints:

before
creating proxy: _value
running proxy: _value
Can't locate object method "TIESCALAR" via package "Some::Package" ...

If a return or my $sub = is added right before sub :lvalue {..., then everything works properly, and it prints:

before
creating proxy: _value
p1 declared: CODE(0x4c7e6c)
creating proxy: value
p2 declared: CODE(0x1ea85e4)

It also works if the :lvalue attribute is removed from the subroutine (but of course that changes the functionality).

So my question is why is this happening? Is this a bug in Perl related to attributes on anonymous subroutines? Is it for some reason an expected behavior? If it is a bug, is it registered?

like image 303
Eric Strom Avatar asked Jan 23 '11 20:01

Eric Strom


1 Answers

Because the beginning of a statement is a valid place to find a goto label, and so the bareword sub followed by a colon token is parsed as the label sub:, which is followed by lvalue BLOCK, which is parsed as indirect object syntax.

If you force the parser to look for a term by doing return sub : lvalue { ... } or my $foo = sub : lvalue { ... } it parses as intended.

like image 167
hobbs Avatar answered Oct 12 '22 09:10

hobbs