元の回答
これを実行する必要がありますperl -MO=Deparse,-p
。コードの最初のビットはこれを示しています:
print(('+' x $z), ((($z = 1), $w) ? '' : $_)) foreach (1 .. 3);
しかし、コードの2番目のビットはこれを示しています。
print($z, ((($z = '+'), $w) ? '' : $_)) foreach (1 .. 3);
困惑し、悩まされている
どうやらそれは一部の人々に問題を十分に説明するには不十分であることがわかった。私はそれが完全に明確だと思っていたので、そうではないはずでした。
受け入れられた解決策は、これが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";
}
これらの3つはすべて、同じ出力を生成します1+2+3
。
2番目のバージョン
ここで、元の文字からやり直します。
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";
}
3つのバージョンはすべて、私が本当に望んでいる理由で、同じ結果を印刷します+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
概要
私は今、ここで実際に起こっていることは、参照渡しとは何の関係もないことを骨の折れる方法で示しました。それは評価の順序だけと関係があり、他には何も関係がありません。