perlは見た目が重要という話
突然ですが以下の実行結果を予測してください。ついでに実行結果と照らし合わせてみてください。
% perl -le 'print 3 ** 2' % perl -le 'print (1+2) ** 2' % perl -le 'print (3) ** 2'
見ただけでオチが分かりましたが何か? → 尊敬させてください
予想通りでしたが何か? → 尊敬させてください
何これ分かんないけど自分で調べるからいいや → さようなら
何これ教えろ → 下に進む
実行結果
こうなる。
% perl -le 'print 3 ** 2' 9 % perl -le 'print (1+2) ** 2' 3 % perl -le 'print (3) ** 2' 3
解説
perlは先の3つの例は、それぞれ以下のように解釈・実行する。
% perl -le 'print 3 ** 2'
3 ** 2 を行った結果をprintする
% perl -le 'print (1+2) ** 2'
print(1+2) を行い、その結果を ** 2 する
% perl -le 'print (3) ** 2'
print(3) を行い、その結果を ** 2 する
というわけで、カッコがprint関数を呼び出すときに使われていたのでした。
納得できない人は
% perldoc perlfunc
もしくは http://perldoc.jp/docs/perl/5.6.1/perlfunc.pod を。
関数に見えるならば、それは関数で、優先順位は関係ありません
と。perlは、printの後ろに () があったからこれはprint関数を呼び出すのに使ってるんだな、と解釈したのでした。
解説2
- print の結果を ** 2 するって何やねん
- perldoc -f print
Returns true if successful.
printに成功したら真を返す。で、その真とやらはスカラ・アレイのどちらのコンテキストで評価しても 1 だった。この例だと左辺で変数に受け取ってないのでvoidコンテキストだけど。
- printの返り値が 1 か。じゃあ 1 ** 2 ってことになって 1 って出力されるはずじゃないの
- この例でいうと出力は副作用みたいなもんです
先の例でprintが行ったのは、あくまで自分に与えられた引数を出力しただけ。この「与えられた引数」っていうのは、それぞれ 3 ** 2 と (1+2) と (3) だ。
print関数からすれば、
- 自分は与えられた値を出力した
- それぞれ 3 **2 = 9, (1+2) = 3, (3) = 3 だった
- 自分の仕事は終わった
だけなのだ。しかし例の2個目と3個目ではperlに食わされた命令はそれで終わらず、
- print関数の仕事の結果(つまり1)に ** 2 するよう命令された
- しかしその結果を受け取る左辺が居ない…何だこの無駄な計算は…
という。
実はこれはwarningsプラグマを使えばちゃんと警告してくれる。
% cat t.pl use warnings; print 3 ** 2; print (1+2) ** 2; print (3) ** 2; % perl t.pl print (...) interpreted as function at t.pl line 4. print (...) interpreted as function at t.pl line 5. Useless use of exponentiation (**) in void context at t.pl line 4. Useless use of exponentiation (**) in void context at t.pl line 5. 933
最初のワンライナーだとwarningsプラグマが有効になってないから何も言われない。
言ってもらうには -w を使う。
% perl -wle 'print 3 ** 2' 9 % perl -wle 'print (1+2) ** 2' print (...) interpreted as function at -e line 1. Useless use of exponentiation (**) in void context at -e line 1. 3 % perl -wle 'print (3) ** 2' print (...) interpreted as function at -e line 1. Useless use of exponentiation (**) in void context at -e line 1. 3
以上。
今日つまづいたところでした。
そうだ海外にも同じところでつまづいた人が居た。
http://www.webmasterkb.com/Uwe/Forum.aspx/perl/26758/1-0-1
% ruby -e 'puts 3 ** 2' 9 % ruby -e 'puts (1+2) ** 2' 9 % ruby -e 'puts (3) ** 2' 9
ruby万歳!