in reply to Re: ||= oddity
in thread ||= oddity

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'

Replies are listed 'Best First'.
Re^3: ||= oddity
by ruzam (Curate) on May 29, 2008 at 13:47 UTC
    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.
Re^3: ||= oddity
by ikegami (Patriarch) on Jun 24, 2008 at 20:22 UTC

    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.