From: m-72 Date: 2001-03-17T03:13:46+09:00 Subject: [ruby-list:28813] Re: freeze した文字列の書き換えチェック方法 はじめまして、三浦と申します。 ----- Original Message ----- From: To: "ruby mailing list" Sent: Friday, March 16, 2001 8:01 PM Subject: [ruby-list:28796] Re: freeze した文字列の書き換えチェック方法 > 値をチェックして代入したり例外を発生するクラスを定義すれば OK か > ---------------------------------------------------------------- > こんなことをするクラスを作ってみました。手抜きの固まりなので、 ・ 複数の変数を監視できない ・ 基本的に監視するのはローカル変数だけ ・ クロージャーやbindingで環境を引き回したことは考えてない ・ 効率が悪そう です。 使い方は、 w = Watch.new w.set_watch('監視する式') 値が変わったときに実行するブロック とします。 ブロックは引数を1つとって新しい式の値が入ります。 監視する式は文字列で指定します。 サンプルプログラムです。 def bar a = 4 a = 5 end def foo a = 1 w = Watch.new w.set_watch('a') {|val| print "Changed to #{val} \n"} a = 2 bar a = 3 end a = 3 foo a = 4 これと後につけるWatchクラスをwatch.rbに書き込んで 実行すると、次のような結果になります。 e:\work\ruby>\usr\local\bin\ruby -v \usr\local\bin\ruby -v ruby 1.6.2 (2000-11-08) [i386-cygwin] e:\work\ruby>\usr\local\bin\ruby watch.rb \usr\local\bin\ruby watch.rb Changed to 2 Changed to 3 e:\work\ruby> ----- class Watch Undefval = [0] def initialize @level = 1 @exp = "" @expval = Undefval @blk = nil end def set_watch(exp, &blk) @blk = blk @exp = exp set_trace_func proc{|event, file, line, id, binding, klass| nlevel = @level case event when 'call', 'class' nlevel = nlevel + 1 @level = @level + 1 when 'return', 'end' nlevel = nlevel - 1 if nlevel < 0 then set_trace_func nil end end if @level == 0 then val = eval @exp, binding if @expval == Undefval @expval = val elsif @expval != val then @blk.call(val) @expval = val end end @level = nlevel } end end