2014-04-14 21 views
8

Quando si tenta di assegnare una variabile e verificarla per definizione in un'operazione in Perl, come sarebbe utile ad esempio in una condizione di if, mi sembrerebbe naturale scrivere:Comprensione delle priorità quando si assegna e verifica la definizione in Perl

if (defined my $thing = $object->get_thing) { 
    $thing->do_something; 
} 

per quanto riguarda la mia comprensione va, defined ha la precedenza di un rightward list operator, che è inferiore a quello della cessione, quindi mi aspetto che il mio codice qui sopra per essere equivalente a:

if (defined (my $thing = $object->get_thing)) { 
    $thing->do_something; 
} 

Mentre il secondo, il codice tra parentesi funziona, il primo restituisce il seguente errore fatale: "Impossibile modificare l'operatore definito nell'assegnazione scalare".

Non è un grosso problema dover aggiungere parentesi, ma mi piacerebbe capire perché la prima versione non funziona, ad es. che tipo di "cosa" è defined e qual è la sua precedenza?

risposta

10

operatori con nome sono divisi in operatori unari (operatori che prendono sempre esattamente un operando) e operatori di lista (tutto il resto) [1].

defined e my[2] sono operatori unari, che hanno la precedenza molto più elevato rispetto ad altri operatori con nome.

Lo stesso vale per i sottotitoli, quindi li userò per dimostrare.

$ perl -MO=Deparse,-p -e'sub f :lvalue {} sub g :lvalue {} f g $x = 123;' 
sub f : lvalue { } 
sub g : lvalue { } 
f(g(($x = 123))); 
-e syntax OK 

$ perl -MO=Deparse,-p -e'sub f($) :lvalue {} sub g($) :lvalue {} f g $x = 123;' 
sub f ($) : lvalue { } 
sub g ($) : lvalue { } 
(f(g($x)) = 123); 
-e syntax OK 

Ma, naturalmente, defined non è una funzione lvalue, in modo da trovare sul LHS di una cessione si traduce in un errore.


  1. and, or, not, xor, lt, le, gt, ge, eq, ne e cmp non sono considerati operatori di nome.

  2. my è molto insolito. Oltre ad avere un effetto sia in fase di compilazione che in fase di esecuzione, la sua sintassi varia a seconda che i parenti siano utilizzati attorno al/ai suo argomento/i. Senza paren, è un operatore unario. Con Parens, è un operatore di elenco.

+0

Sapete cosa determina che 'defined' ha precedenza più alta dell'assegnazione? Ad esempio, 'print my $ test = 'test'' stampa" test ". – scozy

+0

Ho aggiornato la mia risposta. – ikegami

+0

@scozy: non pensare a "mio" come a un operatore con precedenza. La parola chiave "my" induce un'analisi speciale. – gensym