#shibuya.pmで質問してきた

http://d.hatena.ne.jp/foosin/20090403/1238773016の挙動について質問してきた。
配列がスカラーで評価されてるとは思ってたけど、その理由と、perlがどう解釈してるかは分からなかった。


名前考えるのがめどかったのでfoosinでメインマシンから入室。や、サーバマシンの方のは別名で入りっ放しなんだけど。

すいません、質問したいことがあります。配列の && をとったところ、以下のような結果になったのですが、何故この二つのコードの結果が違うのでしょうか?

perl -MData::Dumper -le 'my @x = (); @x = () && (); print Dumper \@x;'
$VAR1 = [
          undef
        ];
perl -MData::Dumper -le 'my @x = (); @x = @x && (); print Dumper \@x;'
$VAR1 = [
          0
        ];
  • typestarさん

my @x = (); @x = (@x) && ()

空リストとして評価されたってことでいい…のかな。


で、ここにも神がいるw

こう評価されてると思う

% perl -MData::Dumper -le 'my @x = (); print Dumper [scalar +()];'
$VAR1 = [
          undef
        ];
% perl -MData::Dumper -le 'my @x = (); print Dumper [scalar @x];'
$VAR1 = [
          0
        ];


Q.何でDumperにアレイref?
A.元のコードとダンプ結果の表示を合わせるため


この辺で演算子の優先順位に思い当たる。

% perldoc perlop

Operator Precedence and Associativity
With very few exceptions, these all operate on scalar values only, not array values.

少しの例外と共に、これらのオペレータはスカラーでのみ評価されます。アレイじゃないよ。

少しの例外…中には例外もある、って感じかね?


で、 && は () より相当低い。それどころか、 () は最強。
なので、

@x = () && ();

は、左の()、右の()の順で評価される。左の()を評価したら偽なので、そこで右辺全体の評価が終了、最後に評価した値、()をスカラーで評価したundefが返って終了。

@x = @x && ();

は、@x、()の順で評価され、@xを評価して偽、右辺全体の評価が終了、だが@xをスカラーで評価すると0になるので0が返る。


ほんとに左→右の順番で評価されるのかなーと思ってre.plで検証。

$ sub p {warn Dumper shift}
$ sub left {p 'left'}
$ sub right {p 'right'}
$ (left()) && (right())
$VAR1 = 'left';
$VAR1 = 'right';

左から右で合ってた。



で、求めてる以上の事をするのが神。

% perl -MData::Dumper -le 'my @x = (); @x = (()=()) && (); print Dumper \@x;'
$VAR1 = [
          0
        ];

こうすればリストの個数評価にできる


要素がundefが1個の配列をスカラーで評価してるのか?と思う俺。
はい間違い。
神による解説。

perl -le 'print scalar +(()=())'

これの実行結果は0で

perl -le 'print scalar +()'

これの実行結果はundefなんだけど
()=()ってやつの()=ってのは何がしたいかっつーと
右辺をリストとして評価するためにやってる

% perl -le 'print $a = (3,2,1,0)'
0
% perl -le 'print $a = ()=(3,2,1,0)'
4

上みたいに評価されるのを下みたいに評価したいときに使う


左辺がスカラーかアレイかで、右辺の評価コンテキストも変わるのを利用して、左辺に空リストを持ってきて、右辺をリストとして評価した、と。
解説聞いてて俺の脳が処理能力超えた。


でだ。
&&は左結合。だから、@x = () && (); の評価結果が scalar +() になって、 @x = @x && (); の評価結果が scalar @xになる。
のは分かる。
が、左辺に @x = と書かれてて、アレイコンテキストのはずなのに、何故右辺の評価結果がスカラーで返るのか分からなかった。
そこでまた演算子の結合順位。
= は && より結合順位が高い。&& は対象をスカラーで評価する。だから。


相当疲れた。頭が。普段結合順位とか気にしないし疎かにしまくってるから理解に時間かかった。
何か変な挙動したら()付けて間に合わせてるからなー。


と、風邪で熱出して死にそうになってる神から色々教わったログ。
多分他人様から見たら分かりづらい。

というわけで

ありがとうございました。>答えてくれた人と神