From: Paul Brannan Date: 2002-03-01T00:34:49+09:00 Subject: Re: RCR?: parallel to until: as_soon_as On Thu, Feb 28, 2002 at 06:37:58AM +0900, Tobias Reif wrote: > I still think a very simple construct for firing a block as soon as / > each time a condition turns true would be useful. No code inside the > class is required; just do observe visible objects and their state. Useful, but slow. If you don't mind slow, then the following solution will work (I've trimmed this down to make it succinct; the full version of this code has a little more error checking): # A hack to temporarily turn off $VERBOSE def verbose_off verbose = $VERBOSE $VERBOSE = false yield $VERBOSE = verbose end # A hack to allow multiple trace funcs verbose_off do $trace_funcs = [] module Kernel set_trace_func_orig = method(:set_trace_func) @@fix_trace_func = proc { if $trace_funcs.size == 0 then set_trace_func_orig.call(nil) elsif $trace_funcs.size == 0 then set_trace_func_orig.call($trace_funcs[0]) else set_trace_func_orig.call(proc { |*args| $trace_funcs.each { |trace_func| trace_func.call(*args) } }) end } def set_trace_func(func) $trace_funcs.push(func) @@fix_trace_func.call() end end end # A hack to allow access to the binding of the caller $call_stack = [] set_trace_func(proc {|*args| case args[0] when "call" $call_stack.unshift($current_call) when "return" $call_stack.shift() end $current_call = args }) def caller_binding(level = 0) $call_stack[level.succ][4] end # A hack to allow a callback to be called the first time an expression # evaluates to true $as_soon_as_expressions = [] set_trace_func(proc {|*args| $as_soon_as_expressions.each_index do |idx| expr, expr_binding, cb = $as_soon_as_expressions[idx] if eval(expr, expr_binding) then $as_soon_as_expressions.delete_at(idx) cb.call() end end }) def as_soon_as(expr, &block) $as_soon_as_expressions.push [expr, caller_binding(), block] end # Some test code $x = 0 as_soon_as "$x == 42" do puts "woohoo!" end puts "1" $x = 1 puts "2" $x = 2 puts "3" $x = 3 puts "42" $x = 42 puts "done" I hope you can see and appreciate just how sick this code really is. Paul