前田です。 matz / netlab.co.jp (Yukihiro Matsumoto) wrote: >あ,ゴマカすって,インスタンス変数には使えない名前があるって >ことだったんですねえ.やっぱり見落としでした.これだったらイ >ンスタンス変数名は > > @__#{id}__ > >にしたらどうでしょう.展開すると @__5879__ みたいな感じにな >ります. なるほど。 >|そういえば、このonceは各インスタンス毎に一回ずつ評価される >|のですが、Eiffelの場合全部のインスタンスを通じて一回しか >|評価されなかったような気がします。 >|どちらの動作が望ましいのでしょう。 > >きっと,Eiffel流でしょうね.その場合はどうやって実装するのが >望ましいかな.インスタンス変数ではなく,定数でテーブルを用意 >するのかな. そうですね。 メソッド本体と同様にHashで管理するようにしてみました。 -- 前田 修吾 ---------- # once-method.rb module OnceMethod BODIES = {} VALUES = {} end class Object private def def_once_method(name, &body) if name.kind_of? Integer name = name.id2name end OnceMethod::BODIES[body.id] = body def_once_method_i(name, body.id) end def def_once_method_i(name, id) eval %{ def #{name} eval 'def #{name}; OnceMethod::VALUES[#{id}]; end', TOPLEVEL_BINDING OnceMethod::VALUES[#{id}] = OnceMethod::BODIES[#{id}].call OnceMethod::BODIES.delete(#{id}) OnceMethod::VALUES[#{id}] end }, TOPLEVEL_BINDING end end class Module private def def_once_method_i(name, id) module_eval %{ def #{name} #{self}.module_eval 'def #{name}; OnceMethod::VALUES[#{id}]; end' OnceMethod::VALUES[#{id}] = instance_eval(&OnceMethod::BODIES[#{id}]) OnceMethod::BODIES.delete(#{id}) OnceMethod::VALUES[#{id}] end } end end