From: "Y. NOBUOKA" Date: 2010-09-21T16:43:59+09:00 Subject: [ruby-list:47470] Re: 変数の変更を監視するには? 信岡です >> 最初の@var=nilが出てくるのは、TEST.newのTESTが評価 >> された時のようです。トップレベルの@varが出力されています。 > > トップレベルの@var? > > というところでちょっと引っ掛かっていますが > ということはインスタンス変数を定義するとトップレベルでも > その変数が評価されている?ということですね。 > # 別のところで疑問がわき出ていますが。。。 いえ、インスタンス変数を定義するとトップレベルでもその変数が評価される、というわけではありません。 Kernel#set_trace_func メソッドは、『Ruby インタプリタがプログラムを実行する過程で、メソッドの呼び出しや式の評価などのイベントが発生する度に、引数として渡された Proc オブジェクトを実行する』 というものです。 つまり、様々なイベントによって set_trace_func メソッドに渡した Proc オブジェクトが実行されます。 今回の例では、TEST オブジェクトのインスタンスが変更されたときだけでなく、トップレベルの命令文 (21 行目から 23 行目にかけての命令文) が実行される際にも以下の手続きが実行されるわけです。 > proc {|event, file, line, id, binding, klass, *rest| > if event == 'line' || event == 'return' > begin > v = eval('@var', binding) > puts "#{file}:#{line}: @var=#{v.inspect}" if old_v != (old_v = v) > rescue NameError > end > end で、この手続きの中身を見るとわかるように、イベント発生箇所の変数スコープで変数 @var を評価して、前回の評価時からかわっていれば出力する、となっています。 > test.rb:21: @var=nil > test.rb:23: @var=nil 上記のような出力がされるのは、トップレベルのスコープで @var を評価して、それを出力しているからです。 今回の例の set_trace_func メソッドを呼び出している箇所を次のように変更すると、どうなっているのかわかりやすいと思います。 一度お試しください。 set_trace_func proc {|event, file, line, id, binding, klass, *rest| if event == 'line' || event == 'return' begin v = eval('@var', binding) puts "#{file}:#{line}: @var=#{v.inspect} (#{event}, #{id.inspect}, #{klass.inspect})" # if old_v != (old_v = v) rescue NameError end end } -- 信岡 裕也 (NOBUOKA Yuya) e-mail: nobuoka@r-definition.com