2011-01-23 4 views
9

Nella seguente dichiarazione subroutine anonima, Perl sembra essere l'analisi come un metodo di chiamata indiretta, piuttosto che come una subroutine:Perché questa dichiarazione di subroutine anon è analizzata come metodo di un oggetto indiretto in Perl?

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"; 

che stampa:

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

Se un return o my $sub = è aggiunto prima dello sub :lvalue {..., quindi tutto funziona correttamente e viene stampato:

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

Funziona anche se l'attributo :lvalue viene rimosso dalla subroutine (ma ovviamente cambia la funzionalità).

Quindi la mia domanda è: perché sta succedendo? Si tratta di un bug in Perl correlato agli attributi su subroutine anonime? È per qualche ragione un comportamento atteso? Se si tratta di un bug, è registrato?

risposta

15

perché l'inizio di una dichiarazione è un luogo valida per trovare un'etichetta goto, e così il bareword sub seguita da un token del colon viene analizzato come l'etichetta sub:, che è seguita da lvalue BLOCK, che viene analizzato come sintassi oggetto indiretto .

Se si forza il parser a cercare un termine eseguendo return sub : lvalue { ... } o my $foo = sub : lvalue { ... }, esso analizza come previsto.