2014-04-14 21 views
8

Podczas próby przypisania zmiennej i przetestowania jej pod kątem zdefiniowania w jednej operacji w Perlu, jak byłoby to przydatne na przykład w stanie if, wydaje mi się naturalne, że napisać:Zrozumienie pierwszeństwa przy przypisywaniu i testowaniu definiowalności w Perl

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

Jeśli chodzi o moje rozumienie idzie, defined ma pierwszeństwo w rightward list operator, która jest niższa niż w przypadku zadania, dlatego spodziewałbym mój kod powyżej, aby być równoważne:

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

Podczas gdy drugi, kod z nawiasami działa, ten pierwszy powoduje następujący błąd krytyczny: "Nie można zmodyfikować zdefiniowanego operatora w przypisaniu skalarnym".

Nie trzeba dodawać nawiasów, ale chciałbym zrozumieć, dlaczego pierwsza wersja nie działa, np. jaka jest "rzecz" defined i jakie jest jej pierwszeństwo?

Odpowiedz

10

nazwane operatorzy dzielą się jednoargumentowych operatorów (operatorów, którzy zawsze biorą dokładnie jeden argument) i lista operatorów (wszystko inne) [1].

defined i my[2]unarne operatorzy, które mają znacznie wyższy priorytet niż inne wymienionych operatorów.

To samo dotyczy subs, więc wykorzystam je do zademonstrowania.

$ 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 

Ale oczywiście defined nie jest lwartością funkcja, więc ze znalezieniem go na LHS od uzyskania wyników przydziału w błąd.


  1. and, or, not, xor, lt, le, gt, ge, eq, ne i cmp nie są uważane za wymienione podmioty.

  2. my jest bardzo nietypowy. Oprócz tego, że ma on zarówno efekt kompilacji, jak i czas działania, jego składnia zmienia się w zależności od tego, czy używane są puste argumenty wokół argumentów, czy też nie. Bez parens to operator jednoargumentowy. W przypadku parens jest operatorem listy.

+0

Czy wiesz, co decyduje, że 'określony' ma wyższy priorytet niż przypisanie? Na przykład 'print my $ test = 'test'' drukuje" test ". – scozy

+0

Zaktualizowałem moją odpowiedź. – ikegami

+0

@scozy: nie myśl o "moim" jako operator z pierwszeństwem. Słowo kluczowe "moje" wywołuje specjalne przetwarzanie. – gensym