4x{d} の続き

4x{d} - 昨日知ったことにコメントをいろいろいただいたのでさらに調査してみた。

print ()+{}

'print ()+{}' は、「print ($_)」の評価結果と無名ハッシュ「{}」の評価結果を加える、というものらしい。

[takeyuki@sunya ~]$ perl -MO=Deparse -e 'print ()+{}'
print($_) + {};
-e syntax OK

つまり、print はリストを引数に持つわけだけれど、その引数として空のリスト「()」を渡したことになり、そしてそれは引数なしで「print」していることになり、それは perl らしく引数を指定しない場合は匿名変数を「$_」を渡しているとみなされる、ということだろう。そんなわけで、

[takeyuki@sunya ~]$ ps | perl -ne 'print ()+{}'
  PID TTY          TIME CMD
 5069 pts/4    00:00:00 bash
18820 pts/4    00:00:00 ps
18821 pts/4    00:00:00 perl

となる。

print {}+()

まず、'print {}' の場合、無名ハッシュは print ステートメントの引数として渡され、print ステートメントの中でそれを文字列コンテキストで評価しようとする。のでエラーにはならず、アドレスが表示される。しかし、'print {}+()' の場合、先に「{}+()」を解釈し、それを print ステートメントの引数にしようと構文解析を試みる。が、「{}+」の時点であり得ないコードと解釈される。+ が単項演算子でもおかしいし、二項演算子でもおかしい。

:-x

こいつはまだ謎のまま。

[takeyuki@sunya ~]$ perl -MO=Deparse -e ':-x'
-x $_;
-e syntax OK

意外だったのはマイナス単項演算子+bare word 文字列「x」だと思っていたのが、ファイルテスト演算子「-x」だったこと、そして例によって「$_」を引数に取っているところ。結局よくわからないのが、「:」の解釈。長さ 0 のラベルなのか、attribute*1なのか。三項演算子ではないだろう。
「:」の謎は続く。

[takeyuki@sunya ~]$ for c in ':;' ':_;' ':3' ':_:' ':while(){last:;}'; do echo "---$c---"; perl -MO=Deparse -e "$c"; done
---:;---
-e syntax OK
---:_;---
'???';
-e syntax OK
---:3---
'???';
-e syntax OK
---:_:---
_: ;
-e syntax OK
---:while(){last:;}---
while (1) {
    last: ;
}
-e syntax OK

'???' も気になる。たいがい「:」はなかったものに解釈されているけれど、last の後に普通についているのも気になる。
シェルコマンドの「:」と関係あるんだろうか。

[takeyuki@sunya ~]$ for x in `seq 3`; do : $x ; done

関係ないよなあ。

追記

http://fleur.hio.jp/perldoc/mix/lib/B/Concise.html使えばコンパイルエラーのときも含めてもっとわかるだろう。けど、今日はこの辺りまで。

*1:よくわかってないけど