It turns out that your assumption is not correct. In both scenarios foo() result is used in list context. This snippet of code will demonstrate it:
#!/usr/bin/perl -w use strict; sub foo { return (10,11,12,13); } my $ret = 0; my $ret2= 0; # EXPRESSION A ($ret,$ret2)||= foo(); print "ret=$ret ret2=$ret2\n"; # ret2 returns 13, last element of list # ret remains unused (warning raised) $ret=0; # EXPRESSION B ($ret) = ($ret) || foo(); print "ret=$ret\n"; # returns 10, first element of list
What drives the whole problem (and solution) is that the '||' operator returns the last value evaluated. And that's where the catch is!
Expression A evaluates the last element of ($ret,$ret2) against the last element of what foo() returns. Since what is listed on the lefthand of the '=' is part of the expression, only the last element of the left-hand operand gets updated.
In Expression B first Perl evaluates the expression on the righthand of the '='. The last values of the (righthand) operands are compared and because $ret is zero this option is discarded and the next operand, foo() is taken. So the result of the expression is foo's list (yes, all elements!). Subsequently this result gets assigned to what is on the lefthand of the '='.
All this shows that it can be tricky to use the '||' operator in a list context. The net result is not obvious and probably one wants to surround any such expression with a little bit of inline documentation so ease code maintenance. Frankly, for myself I would stay away from the construct where possible (except maybe in a nice JAPH).
Update: 'YAPH'=~s/Y/J/
In reply to Re: Why are "a ||= b" and "a = a || b" different?
by varian
in thread Why are "a ||= b" and "a = a || b" different?
by saintmike
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |