「3日目」の章、の2日目。
- 作者: Bruce A. Tate,まつもとゆきひろ,田和勝
- 出版社/メーカー: オーム社
- 発売日: 2011/07/23
- メディア: 単行本(ソフトカバー)
- 購入: 9人 クリック: 230回
- この商品を含むブログ (64件) を見る
メッセージで自分が持っていないスロットを指定された場合にはプロトタイプにforward
Rubyには呼び出されたメソッドが未定義だった場合に呼び出される[http://doc.ruby-lang.org/ja/1.8.7/method/Object/i/method_missing.html:title=method_missing]
メソッドがありますが、Ioで同様の動作をするのがforward
メソッドです。
Io> foo := Object clone ==> Object_0x4e4bf0: Io> foo hoge Exception: Object does not respond to 'hoge' --------- Object hoge Command Line 1 Io> foo forward := method("[foo " .. call message name .."]") ==> method( "[foo " .. call message name .. "]" ) Io> foo hoge ==> [foo hoge]
foo
にhoge
メッセージを送ったとき、forward
に細工をする前はfoo
はhoge
に応答できませんが、forward
を定義してやるとメッセージに応答するメソッドがなかった場合に動作しているのがわかります。
Ruby on Railsはこのしくみを効果的に使って実現しています(記憶が正しければ)。
練習の題材に、役に立ちそうな立たなそうな「ローマ数字を解釈する」というのを選んでみました。
まず。Number VI
とやると6
と返ってくるようにしてみます。
このためにRomanNumeral
というオブジェクトをインポートしていますが、これは話題の中心でないので後ろの方で解説します。文字列に対してたとえば"VI" fromRomanNumeral
とすると数値の6が返るようなしくみを実現している、とだけ覚えておいてください。
まず。そのままではメッセージに応答できないことを確認。
Io> Number VI Exception: Number does not respond to 'VI' --------- Number VI Command Line 1
RomanNumeral
を読み込んで、Number
のforward
を書き換えます。
Io> RomanNumeral ==> RomanNumeral_0x5f6840: C = 67 D = 68 I = 73 L = 76 M = 77 RomanNumeralDigits = "MDCLXVI" V = 86 X = 88 fromRomanNumeral = method(...) romanNumeralDigit = method(s, ten, five, one, ...) type = "RomanNumeral" Io> Number forward := method(n := call message name fromRomanNumeral; if(n != 0, n, nil)) ==> method( n := call message name fromRomanNumeral; if(n != 0, n, nil) )
実行結果。
Io> Number VI ==> 6 Io> Number III ==> 3 Io> Number IIII ==> nil
メッセージ名をローマ数字と解釈して数値に変換されているのがわかります。
マスター名前空間でもforwardする
Ioではすべてのメッセージにレシーバがいて、レシーバを指定しなかったばあいはマスター名前空間(いわゆるグローバルな空間)のオブジェクトにメッセージが送られます。
と、いうこととは。マスター名前空間にもforward
を定義することができます。
Io> forward := method(n := call message name fromRomanNumeral; if(n != 0, n, nil)) ==> method( n := call message name fromRomanNumeral; if(n != 0, n, nil) ) Io> VI ==> 6 Io> III ==> 3 Io> MCMXCIX ==> 1999
計算もできます(数値ですから)。
Io> XXXIII + LXV ==> 98 Io> XXXIII + LXV * X ==> 683
なんかあっさり片付いてしまった気がする。
そんなわけで、つづく。あとひとつ、の予定。
ローマ数字パーサの実装
ここからは補足。