Original answer
You need to run this through perl -MO=Deparse,-p . The first bit of code shows this:
print(('+' x $z), ((($z = 1), $w) ? '' : $_)) foreach (1 .. 3);
But the second bit of code shows this:
print($z, ((($z = '+'), $w) ? '' : $_)) foreach (1 .. 3);
Confused and Carefree
Apparently, this turned out to be insufficient to sufficiently explain some issues. It should not have been, as I considered it perfectly clear.
The decision mistakenly claims that this is somehow due to the fact that Perl passes scalar variables by an implicit reference. This has nothing to do with it. This is a simple question about the priority and order of evaluation. I assumed Deparse's exit should make this clear.
Apparently, some of them are still confused.
First version
Very good, here is your explanation that you spend on a silver dish for you.
It:
print'+'x$z,($z=1,$w)?'':$_ for 1..3;
equivalent, kindly provided by Deparse and some additional formation:
{ ($w, $z) = (undef, undef); for (1..3) { print(("+" x $z), ((($z = 1), $w) ? "" : $_)) } } continue { print "\n"; }
Now, by unrolling the cycle and separating what happens when it is created:
{ ($w, $z) = (undef, undef); { local $_ = 1; $temp = "+" x $z;
All three of them produce identical output: 1+2+3 .
Second version
Now we will start again with the original:
print$z,($z='+',$w)?'':$_ for 1..3;
and create a version to delete:
{ ($w, $z) = (undef, undef); for (1..3) { print($z, ((($z = "+"), $w) ? "" : $_)); } } continue { print "\n"; }
followed by the loop version:
{ ($w, $z) = (undef, undef); { local $_ = 1; $z = "+"; print $z, $_; } { local $_ = 2; $z = "+"; print $z, $_; } { local $_ = 3; $z = "+"; print $z, $_; } } continue { print "\n"; }
All three versions, for reasons I REALLY HOPE THAT YOU NEED TO CLEAN, will print the same result: +1+2+3 .
For further enlightenment
The best way to track what happens when you need to trace it:
tie $z, "Tie::Trace", "z"; tie $w, "Tie::Trace", "w"; ($w, $z) = (undef, undef); print'+'x$z,($z=1,$w)?'':$_ for 1..3; print "\n"; { ($w, $z) = (undef, undef); for (1..3) { print(("+" x $z), ((($z = 1), $w) ? "" : $_)) } } continue { print "\n"; } { ($w, $z) = (undef, undef); { local $_ = 1; $temp = "+" x $z;
When you run this, it produces this pretty nice conclusion:
[writing value undef into $w] [writing value undef into $z] [reading value undef from $z] [reading value undef from $z] [writing value 1 into $z] [reading value undef from $w] [reading value 1 from $z] [reading value 1 from $z] [writing value 1 into $z] [reading value undef from $w] [reading value 1 from $z] [reading value 1 from $z] [writing value 1 into $z] [reading value undef from $w] 1+2+3 [writing value undef into $w] [writing value undef into $z] [reading value undef from $z] [reading value undef from $z] [writing value 1 into $z] [reading value undef from $w] [reading value 1 from $z] [reading value 1 from $z] [writing value 1 into $z] [reading value undef from $w] [reading value 1 from $z] [reading value 1 from $z] [writing value 1 into $z] [reading value undef from $w] 1+2+3 [writing value undef into $w] [writing value undef into $z] [reading value undef from $z] [reading value undef from $z] [writing value 1 into $z] [reading value 1 from $z] [reading value 1 from $z] [writing value 1 into $z] [reading value 1 from $z] [reading value 1 from $z] [writing value 1 into $z] 1+2+3 [writing value undef into $w] [writing value undef into $z] [writing value + into $z] [reading value undef from $w] [reading value + from $z] [writing value + into $z] [reading value undef from $w] [reading value + from $z] [writing value + into $z] [reading value undef from $w] [reading value + from $z] +1+2+3 [writing value undef into $w] [writing value undef into $z] [writing value + into $z] [reading value undef from $w] [reading value + from $z] [writing value + into $z] [reading value undef from $w] [reading value + from $z] [writing value + into $z] [reading value undef from $w] [reading value + from $z] +1+2+3 [writing value undef into $w] [writing value undef into $z] [writing value + into $z] [reading value + from $z] [writing value + into $z] [reading value + from $z] [writing value + into $z] [reading value + from $z] +1+2+3
Summary
Now, I have barely demonstrated that what is actually happening here has nothing to do with passing by reference. This is only due to the order of evaluation, and nothing more.