Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding precedence when assigning and testing for definedness in Perl

When trying to assign a variable and test it for definedness in one operation in Perl, as would be useful for instance in an if's condition, it would seem natural to me to write:

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

As far as my understanding goes, defined has the precedence of a rightward list operator, which is lower than that of the assignment, therefore I would expect my code above to be equivalent to:

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

While the latter, parenthesised code does work, the former yields the following fatal error: "Can't modify defined operator in scalar assignment".

It's not a big deal having to add parentheses, but I would love to understand why the first version doesn't work, e.g. what kind of "thing" defined is and what is its precedence?

like image 634
scozy Avatar asked Apr 14 '14 13:04

scozy


1 Answers

Named operators are divided into unary operators (operators that always take exactly one operand) and list operators (everything else)[1].

defined and my[2] are unary operators, which have much higher precedence than other named operators.

The same goes for subs, so I'll use them to demonstrate.

$ 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

But of course, defined is not an lvalue function, so finding it on the LHS of an assignment results in an error.


  1. and, or, not, xor, lt, le, gt, ge, eq, ne and cmp are not considered named operators.

  2. my is very unusual. Aside from having both a compile-time and run-time effect, its syntax varies depending on whether parens are used around its argument(s) or not. Without parens, it's a unary operator. With parens, it's a list operator.

like image 135
ikegami Avatar answered Oct 19 '22 19:10

ikegami