in reply to ||= oddity

In order to do what I believe you intend, you'll need to use:
@bar = (1,2,3) unless @bar;
What is interesting is that this prints x:
$bar ||= (1,2,'x'); print $bar, "\n";
So perhaps the RHS is not being interpreted as a list constructor but as a sequence of expressions whose value is the last expression. That would explain this behavior:
my ($a, $b); ($a, $b) ||= ('a', 'b', 'c'); # $a unchanged, $b <- 'c' ($a, $b) ||= (1, 2, 3); # $a unchanged, $b unchanged $b = (1, 2, 'x'); # $b <- 'x' $a ||= (3, 4, 5); # $a <- 5
So it appears that ($a, $b) on the LHS is being interpreted as a sequence (not list constructor) of l-values whose value is the last (l-value) expression. However, in this case:
($a, $b) = (7,8,9); # $a <- 7, $b <- 8
we have list constructors on both the LHS and RHS.

Replies are listed 'Best First'.
Re^2: ||= oddity
by kyle (Abbot) on May 28, 2008 at 20:47 UTC

    A list is a sequence of expressions. How context propagates into that list has been the subject of much discussion. Here's a conversation piece:

    sub wa { my $place = shift @_; my $context = wantarray ? 'list' : defined wantarray ? 'scalar' : 'void'; warn "'$context' context at '$place'\n"; } my $x ||= (wa('oe1'),wa('oe2'),wa('oe3')); print "\n"; my $y = (wa('e1'),wa('e2'),wa('e3')); print "\n"; my $z = sub { (wa('s1'),wa('s2'),wa('s3')) }->(); __END__ 'void' context at 'oe1' 'void' context at 'oe2' 'scalar' context at 'oe3' 'void' context at 'e1' 'void' context at 'e2' 'scalar' context at 'e3' 'scalar' context at 's1' 'scalar' context at 's2' 'scalar' context at 's3'
      That is surprising. I would have expected the interpreter to be smarter about the list context and skip over evaluating all but the last item. That seems like a obvious optimization opportunity.

      Hmmm... Then again, I probably wouldn't put 3 sub calls in a list if I only meant to evaluate and assign the last.

      Interesting. It appears to be the result of compile-time optimization. (Update: Or maybe it's to generate the "useless use of a constant in void context" warning.)

      sub wa { my $place = shift @_; my $context = wantarray ? 'list' : defined wantarray ? 'scalar' : 'void'; warn "'$context' context at '$place'\n"; } my $x = (wa('a1'),wa('a2'),wa('a3'));

      is compiled to

      >perl -MO=Concise script.pl j <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 4 script.pl:8) v ->3 i <2> sassign vKS/2 ->j g <@> list sKP ->h 3 <0> pushmark v ->4 7 <1> entersub[t3] vKS/TARG,1 ->8 ^ | void context - <1> ex-list K ->7 4 <0> pushmark s ->5 5 <$> const[PV "a1"] sM ->6 - <1> ex-rv2cv sK/1 ->- 6 <#> gv[*wa] s ->7 b <1> entersub[t5] vKS/TARG,1 ->c ^ | void context - <1> ex-list K ->b 8 <0> pushmark s ->9 9 <$> const[PV "a2"] sM ->a - <1> ex-rv2cv sK/1 ->- a <#> gv[*wa] s ->b f <1> entersub[t7] sKS/TARG,1 ->g ^ | scalar context - <1> ex-list sK ->f c <0> pushmark s ->d d <$> const[PV "a3"] sM ->e - <1> ex-rv2cv sK/1 ->- e <#> gv[*wa] s ->f h <0> padsv[$x:4,5] sRM*/LVINTRO ->i script.pl syntax OK

      So,
      if the context of the "," operator is known to be scalar at compile-time, the LHS is evaluated in void context.
      if the context of the "," operator is known to be list at compile-time, the LHS is evaluated in list context.
      if the context of the "," operator is not known at compile-time, the LHS is evaluated in the same context as the operator.

Re^2: ||= oddity
by chromatic (Archbishop) on May 28, 2008 at 21:10 UTC
    So perhaps the RHS is not being interpreted as a list constructor but as a sequence of expressions....

    If there is such a thing as a "list constructor" in Perl 5 (and that's up for debate), that's all it is -- a sequence of comma-separated expressions.