Оригинальный ответ
Вам нужно выполнить это через perl -MO=Deparse,-p
.Первый бит кода показывает это:
print(('+' x $z), ((($z = 1), $w) ? '' : $_)) foreach (1 .. 3);
Но второй бит кода показывает это:
print($z, ((($z = '+'), $w) ? '' : $_)) foreach (1 .. 3);
Confusticated и Bebothered
Видимо этого оказалось недостаточно для того, чтобы в достаточной степени объяснить вопросы некоторым людям.Это не должно было быть, поскольку я думал, что это совершенно ясно.
Принятое решение ошибочно утверждает, что это как-то связано с тем, что Perl передает скалярные переменные по неявной ссылке.Это вообще не имеет к этому никакого отношения.Это простой вопрос приоритета и порядка оценки.Я предполагал, что вывод Deparse должен прояснить это.
Видимо, некоторые все еще запутаны.
Первая версия
Очень хорошо, вот ваше объяснение, все изящнона серебряном блюде для вас.
Это:
print'+'x$z,($z=1,$w)?'':$_ for 1..3;
эквивалентно, любезно предоставлено Deparse и некоторому дополнительному форматированию, этому:
{
($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; # $z is undef
$z = 1;
print $temp, $_;
}
{
local $_ = 2;
$temp = "+" x $z; # $z is 1
$z = 1;
$_ = $_;
print $temp, $_;
}
{
local $_ = 3;
$temp = "+" x $z; # $z is 1
$z = 1;
$_ = $_;
print $temp, $_;
}
} continue {
print "\n";
}
Все три из них производят идентичный вывод: 1+2+3
.
Вторая версия
Теперь мы снова начнем с оригинала:
print$z,($z='+',$w)?'':$_ for 1..3;
и создадим отличающуюся версию:
{
($w, $z) = (undef, undef);
for (1..3) {
print($z, ((($z = "+"), $w) ? "" : $_));
}
} continue {
print "\n";
}
, за которой следуетверсия развертки цикла:
{
($w, $z) = (undef, undef);
{
local $_ = 1;
$z = "+";
print $z, $_;
}
{
local $_ = 2;
$z = "+";
print $z, $_;
}
{
local $_ = 3;
$z = "+";
print $z, $_;
}
} continue {
print "\n";
}
Все три версии, по причинам, которые я ДЕЙСТВИТЕЛЬНО НАДЕЖДА СЕЙЧАС ОБОРОТНО ОЧИЩАЮТ выводим тот же результат: +1+2+3
.
Для дальнейшего просвещения
Лучший способ отследить, что происходит, когда поставить на него след:
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; # $z is undef
$z = 1;
print $temp, $_;
}
{
local $_ = 2;
$temp = "+" x $z; # $z is 1
$z = 1;
$_ = $_;
print $temp, $_;
}
{
local $_ = 3;
$temp = "+" x $z; # $z is 1
$z = 1;
$_ = $_;
print $temp, $_;
}
} continue {
print "\n";
}
($w, $z) = (undef, undef);
print$z,($z='+',$w)?'':$_ for 1..3;
print "\n";
{
($w, $z) = (undef, undef);
for (1..3) {
print($z, ((($z = "+"), $w) ? "" : $_));
}
} continue {
print "\n";
}
{
($w, $z) = (undef, undef);
{
local $_ = 1;
$z = "+";
print $z, $_;
}
{
local $_ = 2;
$z = "+";
print $z, $_;
}
{
local $_ = 3;
$z = "+";
print $z, $_;
}
} continue {
print "\n";
}
package Tie::Trace;
sub TIESCALAR {
my($class, $name, $value) = @_;
return bless {
NAME => $name,
VALUE => undef,
} => $class;
}
sub FETCH {
my($self) = @_;
my $name = '$' . $self->{NAME};
my $value = $self->{VALUE};
print STDERR "[reading value ", defined($value) ? $value : "undef",
" from $name]\n";
return $value;
}
sub STORE {
my($self, $value) = @_;
my $name = '$' . $self->{NAME};
print STDERR "[writing value ", defined($value) ? $value : "undef",
" into $name]\n";
$self->{VALUE} = $value;
return $value;
}
Когда вы запустите его, он выдаст довольно приятный результат:
[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
Резюме
Теперь я с трудом продемонстрировал, что то, что на самом деле здесь происходит, не имеет ничего общего с передачей по ссылке.Это связано только с порядком оценки, и ничего больше.