Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

ternary operator as lvalue failing to induce evaluation of right-hand expression in list context

by ed_hoch (Sexton)
on Aug 03, 2013 at 15:44 UTC ( [id://1047720]=perlquestion: print w/replies, xml ) Need Help??

ed_hoch has asked for the wisdom of the Perl Monks concerning the following question:

(on perl v5.16.2)

(time ? @a=() : $a) = Foo();
I would expect the above to give an "Assignment to both a list and a scalar" error, but instead Foo is just evaluated in scalar context. Leaving aside that this is poor code, can someone explain what's going on here? Thanks!

Update: Thanks everyone for all the help. Again, with: This is perl 5, version 16, subversion 2 (v5.16.2) built for x86_64-linux I do:

~home>perl -MO=Concise, -ce '$z = (time ? @x=() : $x) = 365' e <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 1 -e:1) v:{ ->3 d <2> sassign vKS/2 ->e b <2> sassign sKS/2 ->c 3 <$> const(IV 365) s ->4 - <1> null sKPRM*/1 ->b 5 <|> cond_expr(other->6) sKRM*/1 ->f 4 <0> time[t1] s ->5 a <2> aassign[t3] sKRMS* ->b - <1> ex-list lK ->7 6 <0> pushmark s ->7 - <0> stub lP ->- - <1> ex-list lK ->a 7 <0> pushmark s ->8 9 <1> rv2av[t2] lKRM*/1 ->a 8 <$> gv(*x) s ->9 - <1> ex-rv2sv sKRM*/1 ->- f <$> gvsv(*x) s ->b - <1> ex-rv2sv sKRM*/1 ->d c <$> gvsv(*z) s ->d -e syntax OK
versus
~home>perl -MO=Concise, -ce '$z = (time ? (@x=()) : $x) = 365' Assignment to both a list and a scalar at -e line 1, at EOF -e had compilation errors. e <@> leave[1 ref] KP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 1 -e:1) :{ ->3 d <2> sassign KS/2 ->e b <2> sassign KS/2 ->c 3 <$> const(IV 365) s ->4 - <1> null KP/1 ->b 5 <|> cond_expr(other->6) K/1 ->f 4 <0> time[t1] s ->5 a <2> aassign[t3] KPS ->b - <1> ex-list lK ->7 6 <0> pushmark s ->7 - <0> stub lP ->- - <1> ex-list lK ->a 7 <0> pushmark s ->8 9 <1> rv2av[t2] lKRM*/1 ->a 8 <$> gv(*x) s ->9 - <1> ex-rv2sv sK/1 ->- f <$> gvsv(*x) s ->b - <1> ex-rv2sv sK/1 ->d c <$> gvsv(*z) s ->d
There are several differences, starting with the fact that in the first case (the case where it compiles, but I would have expected it not to), apparently the assignment to the ternary is parsed as scalar context (s), where in the second case (the case where it gives compiler errors, as I would have expected), the context isn't indicated. perlop indicates that for a conditional expression, the scalar/list context propagates down to the 2nd or 3rd argument. I suspect something wild is going on with parsing "@x=()" and "(@x=())" as scalar lvalues, where the first is legitimate, and the second isn't. This is really just a guess, though.
  • Comment on ternary operator as lvalue failing to induce evaluation of right-hand expression in list context
  • Select or Download Code

Replies are listed 'Best First'.
Re: ternary operator as lvalue failing to induce evaluation of right-hand expression in list context
by Loops (Curate) on Aug 03, 2013 at 16:21 UTC
    Deparse tells the tale...
    perl -MO=Deparse -e 'sub Foo() {}; (time ? @a=() : $a) = Foo();'
    sub Foo () { } time ? @a = () : $a = Foo;
    and if you try the more natural:
    perl -MO=Deparse -e 'sub Foo() {}; (time ? @a : $a) = Foo();'
    Assignment to both a list and a scalar at -e line 1, near ");"
    Perl needs to examine the left-hand side in order to know the context in which to run Foo(), but it delays execution until Foo() has been run. Therefore it can't decide on the context and fails.

      Deparse shows that the parentheses in the OP are unnecessary, which is as expected, since the conditional operator ?: has a higher precedence than assignment (see Operator Precedence and Associativity). Consider:

      It’s clear that foo is being evaluated in scalar context, even though the condition evaluates to true and so chooses the LHS. Since foo would still be evaluated in scalar context if the condition were false and the RHS chosen, it’s now clear why the compile error has disappeared: it is known at compile time that foo will be evaluated in scalar context.

      But that leaves us with some unanswered questions:

      1. What exactly is the l-value returned by the conditional expression?
      2. Why does this l-value — which results from the assignment of a list to an array — put foo into scalar context?
      3. Why does the assignment to @x seemingly occur after the call to foo?

      I have the feeling that there’s an obvious answer to all this, but I can’t see it. Which is, just possibly, related to the fact that in my neck of the woods the Ashes coverage finishes around 3:30 am... |-O

      Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

        This is strange. The output of Deparse -p is not parsed the same way as the original:
        $ perl -MO=Deparse -e 'sub Foo{};(time ? @y=() : $x) = Foo()' | per +l -e syntax OK $ perl -MO=Deparse,-p -e 'sub Foo{};(time ? @y=() : $x) = Foo()' | per +l -e syntax OK Assignment to both a list and a scalar at - line 4, near "))" Execution of - aborted due to compilation errors.

        Perl 5.10.1

        لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1047720]
Approved by Athanasius
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (3)
As of 2024-04-25 19:00 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found