in reply to my (0?$a:$b): a koan

My guess was either (1,3) or ('', 3), leaning toward the former

I'd probably write the example code like the following to keep it a little simpler and to focus on the actual mechanism that is occuring

my $x = 1; my $y = 2; { my (0?$x:$y) = 3; print "x=$x\ny=$y\n" }

Very interesting result though, thank you for the explanation

Btw, do you have an explanation for why B::Deparse gets it wrong? I've hardly ever used that module so not even sure exactly what it's trying to do.

Replies are listed 'Best First'.
Re^2: my (0?$a:$b): a koan
by educated_foo (Vicar) on May 04, 2011 at 19:46 UTC
    Your version is indeed simpler. I had put the sub call in there to see if I could use a parameter for the ternary test (Perl gets angry about your trying to lexicalize @_ if you do that), but failed to remove it.

    do you have an explanation for why B::Deparse gets it wrong?
    B::Deparse walks through the op-tree reconstructing a Perl program, and I'm guessing that its author didn't anticipate whatever weird optree you get from a ternary inside a "my". That, or it gets defeated by constant folding, just like here:
    $ perl -MO=Deparse -e 'print 0?$a:$b' print $b;
      > or it gets defeated by constant folding

      thats the point, compare the optree of my (0?$a:$b)="X" with my ($b)="X".

      Deparse has no chance to see any difference

      lanx:~$ perl -MO=Concise -e 'my (0?$a:$b)="X";print $a' c <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 1 -e:1) v:{ ->3 7 <2> aassign[t3] vKS ->8 - <1> ex-list lK ->5 3 <0> pushmark s ->4 4 <$> const[PV "X"] s ->5 - <1> ex-list lK ->7 5 <0> pushmark s ->6 6 <0> padsv[$b:1,2] lPRM*/LVINTRO ->7 8 <;> nextstate(main 2 -e:1) v:{ ->9 b <@> print vK ->c 9 <0> pushmark s ->a a <0> padsv[$a:1,2] l ->b -e syntax OK
      lanx:~$ perl -MO=Concise -e 'my ($b)="X";print $a' c <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 1 -e:1) v:{ ->3 7 <2> aassign[t2] vKS ->8 - <1> ex-list lK ->5 3 <0> pushmark s ->4 4 <$> const[PV "X"] s ->5 - <1> ex-list lK ->7 5 <0> pushmark s ->6 6 <0> padsv[$b:1,2] lPRM*/LVINTRO ->7 8 <;> nextstate(main 2 -e:1) v:{ ->9 b <@> print vK ->c 9 <0> pushmark s ->a - <1> ex-rv2sv sK/1 ->b a <#> gvsv[*a] s ->b -e syntax OK

      Note line a: In the first example $a is coded as entry "$a" from a lexical pad and in the second it's the scalar value of glob *a from a symbol table.

      IMHO you found a case where the compiler should better warn about undefined behavior.

      Cheers Rolf

      UPDATE: we had a discussion about this just few weeks ago, but I can't find it. Take this instead: 'my' with 'if 0' retains old value

      UPDATE: And here the warning I'm missing:

      perl -wce 'my $a if 0; print $a' Deprecated use of my() in false conditional at -e line 1. -e syntax OK

      UPDATE: Found it! see A curious case of of my() and Re^4: A curious case of of my() (What is GLOBAL?)

        Nice -- it's a kind of clever inside-out way to say
        my $a if 0; my $b = 3;
        EDIT: As seen with this:
        $a=1; $b=2; sub x { my (0?$a:$b) = shift; print"a=$a\nb=$b\n"; $a=shift } x(3,30); x(4,40); __END__ # OUTPUT: a= b=3 a=30 b=4
      I'm guessing that its author didn't anticipate whatever weird optree you get from a ternary inside a "my".

      There is no "weird optree". By the time Deparse gets its hands on the optree, the ternary has been optimised away.

      What's left is exactly the same as if the ternary (and $a) had never existed in the source.

      If there is a bug, then it is that the optimisation doesn't undo the local declaration of $a.


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.