2014-04-14 15 views
8

Beim Versuch, eine Variable zuzuweisen und sie in einer Operation in Perl auf ihre Definiertheit zu testen, wie es zum Beispiel in einem if Zustand nützlich wäre, würde es mir natürlich erscheinen schreiben:Die Rangfolge beim Zuweisen und Testen der Definiertheit in Perl verstehen

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

Soweit mein Verständnis geht, defined den Vorrang eines rightward list operator hat, die kleiner als die von der Abtretung niedriger ist daher würde ich meinen Code oben erwarten zu sein äquivalent zu:

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

Während letzterer Code in Klammern funktioniert, führt der erste zu dem folgenden schwerwiegenden Fehler: "Definierter Operator kann nicht in skalarer Zuweisung geändert werden".

Es ist keine große Sache, Klammern hinzuzufügen, aber ich würde gerne verstehen, warum die erste Version nicht funktioniert, z. welche Art von "Ding" defined ist und was hat seinen Vorrang?

Antwort

10

Named Betreiber in unäre Operatoren aufgeteilt (Operatoren, die genau ein Operand immer nehmen) und Liste Operatoren (alles andere) [1].

defined und my[2] sind unäre Operatoren, die als andere benannte Betreiber viel höhere Priorität haben.

Das gleiche gilt für Subs, also werde ich sie demonstrieren.

$ 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 

Aber natürlich defined ist keine L-Wert-Funktion, so dass es auf der LHS einer Zuweisung zu einem Fehler zu finden.


  1. and, or, not, xor, lt, le, gt, ge, eq, ne und cmp werden nicht genannt Betreiber berücksichtigt.

  2. my ist sehr ungewöhnlich. Abgesehen davon, dass es sowohl einen Kompilierungszeit- als auch einen Laufzeit-Effekt hat, hängt seine Syntax davon ab, ob Parens um seine Argumente herum verwendet werden oder nicht. Ohne Parens ist es ein unärer Operator. Mit Parens ist es ein Listenoperator.

+0

Wissen Sie, was bestimmt, dass 'definiert' einen höheren Vorrang hat als die Zuweisung? Zum Beispiel "print my $ test = 'test'" druckt "test". – scozy

+0

Ich habe meine Antwort aktualisiert. – ikegami

+0

@scozy: Denken Sie nicht an "mein" als Operator mit Vorrang. Das Schlüsselwort 'my' führt zu einem speziellen Parsing. – gensym