iolanguage メソッドの引数の評価
素朴な疑問にひっかかった。if とか else もメソッドで、引数にメッセージをとるけど、何でこの引数は評価されずに渡されるんだろう。ちょっと解りにくいから実際にコードを書いてみる。
if (Nil) then ( "not print" print ) else ( "print" print )
この場合もちろん not print は出力されないし、それが願う動作。しかしながら "not print" print も引数だから、メソッドに渡される前に評価されて not print と出力されるんじゃないかと悩んだ。というか正確に言えば if をユーザから定義するときに評価されてしまってハマった。以下にハマったコードを示す
myif := method(test, ifObj := Object clone ifObj test := test ifObj do ( mythen := method(msg, if (test, sender doMessage(thisMessage argAt(0))) self ) myelse := method(msg, if (test isNil, sender doMessage(thisMessage argAt(0))) self ) ) ) myif (Nil) mythen ( "nil" print ) myelse ( "aaa" print )
これは予想に反して nilnilaaa と出力される。引数が渡される前に評価されしまっているからだ。リファレンス見ててもよくわからないので、適当に書き直していたらできた。書き直した結果を書いてみる。
myif := method(test, ifObj := Object clone ifObj test := test ifObj do ( mythen := method( if (test, sender doMessage(thisMessage argAt(0))) self ) myelse := method( if (test isNil, sender doMessage(thisMessage argAt(0))) self ) ) )
何が変わったかっていうと method の仮引数を書かないようにしただけ。仮引数を書くと評価されてしまうらしい。微妙な罠。プログラミングガイドに明記してもいいじゃん! とはいえこれを踏まえてから読み直すと The thisMessage slot that is preset (see next section) in locals can be used to access the unevaluated argument messages.
と書かれていてといっても原文は引用しただけで日本語訳から探した。 (強調はされていない) 頭がよければ thisMessage スロットには未評価なメッセージが入っていて、仮引数を書かなくても呼び出せる。もしかして仮引数を書かなければメッセージは評価されないんじゃないか、なんて推論できる (苦しい) かもしれないけど、俺には無理!
関連エントリー
- iolanguage 引数のデフォルト値 リファレンスを見た限りではメソッドの引数を省略したときの値を指定できないっぽい。ようは可変長変数を使うんだと思うんだけど、これまた長い。んな...
- Ruby.each Ruby の each 系メソッドで一つ気に入らないというか、仕方ないんだけど面倒くさいことがある。なにかっていうと index を使いたけ...
- Ruby, ブロック引数をとるメソッド def foo(a, b) yield a + b end def fop(a, b, &block) yield a + b end de...
- 日記スクリプト思考 XML は中間データとして使うようにしてみる。もちろんデータを XML で書いてもいいし、てきとーにデータベースから XML 生成するような...
- class_eval のブロックを与えたときと文字列を与えたときの違い このメソッドの挙動がよくわからない。PluginBase.class_eval(%Q|@@irc = irc|) では思ったとおりだけど、P...