Abyaad
Abyaad

Reputation: 21

Perl: Expression precedence and evaluation

I have the following code:

$codelist = 00;

$OK = '0';
$OK = () = $codelist =~ /$OK/g;

print "$OK\n"; #answer is 2.

How does the expression $OK = () = $codelist =~ /$OK/g is evaluated? What is the order of precedence?

Upvotes: 2

Views: 167

Answers (3)

mob
mob

Reputation: 118595

B::Deparse can show you precedence if you ever get confused.

$ perl -MO=Deparse,-p -e '$OK = () = "00" =~ /0/g'
($OK = (() = ('00' =~ /0/g)));
-e syntax OK

Upvotes: 5

Possum
Possum

Reputation: 557

If you look at perldoc perlop, there is the following precedence chart:

left        terms and list operators (leftward)
left        ->
nonassoc    ++ --
right       **
right       ! ~ \ and unary + and -
left        =~ !~
left        * / % x
left        + - .
left        << >>
nonassoc    named unary operators
nonassoc    < > <= >= lt gt le ge
nonassoc    == != <=> eq ne cmp ~~
left        &
left        | ^
left        &&
left        || //
nonassoc    ..  ...
right       ?:
right       = += -= *= etc. goto last next redo dump
left        , =>
nonassoc    list operators (rightward)
right       not
left        and
left        or xor

From that chart, we look up =~ and = because those are the only operators you have here.

=~ is tighter binding, so that gets evaluated first $OK = () = ($codelist =~ /$OK/g);

Then =in left order...

($OK = () = ($codelist =~ /$OK/g));
($OK = (() = ($codelist =~ /$OK/g)));

Another helpful tool mentioned in other answers is B::Deparse with the -p option. Still, it is a good idea to be familiar with the above chart, or at least know where to reference it.

As a side note, the =()= is a somewhat common idiom, so much so that it has an entry in the perlsecret distribution as the "Goatse" (don't Google that) or "Saturn" secret operator; it is essentially used to force list context to the right side, usually to return the count (since the left side is a scalar).

Upvotes: 4

Georg Mavridis
Georg Mavridis

Reputation: 2331

I assume your example-code starts with

$codelist = '00';

The code

$OK = () = $codelist =~ /$OK/g;

first matches $codelist against 0 globally so it returns ALL matches. But that is only true, when called in a list-context. Otherwise, it would only return whether it matches or not. The assignment-trick with

$OK= () = ...

sets the list-context for the evaluation and evaluates the returned array in the scalar context (which results in the number of elements).

So when you remove the /g in the match, or the () = in the assingement you get 1.

Upvotes: 1

Related Questions