From: Dave Thomas Date: 2000-09-13T01:45:43+09:00 Subject: [ruby-talk:4906] Re: Re-binding a block matz@zetabits.com (Yukihiro Matsumoto) writes: > |The first parameter to the block is a proc object that wraps the > |original routine, and the remaining parameters are those supplied by > |the caller. > > How did you do that. Show me your (imcomplete?) code. This is the version that makes no attempt to execute the function in the object's context. I had to recreate this using about 1,000 emacs undo's, so it may well be buggy, but I hope it gets the idea across. ### # This is the stuff behind the curtain # module Hook @@n = 0 @@hook_function = Array.new def Hook.create(block) @@n += 1 @@hook_function[@@n] = block @@n end def Hook.call(from, n, block, *args, &orig_fn) b.call(orig_fn, *args, &block) end def Hook.getHook(n) b = @@hook_function[n] end end class Module def hook(sym, &block) if block.nil? raise "Missing block to hook function" end n = Hook.create(block) fn = sym.to_s class_eval %{ alias hook_#{n} #{fn} def #{fn}(*args, &block) b = Hook.getHook(#{n}) orig_fn = proc { hook_#{n} } b.call(orig_fn, *args, &block) end } end end ### # and this is the stuff the user sees # class String hook :upcase do |_upcase| _upcase.call.tr('_', '~') end end p "foo_bar".upcase #=> FOO~BAR