From: Adam Fields Date: 2004-07-17T06:08:09+09:00 Subject: Re: Dynamically replacing methods for efficiency On Sat, Jul 17, 2004 at 05:57:14AM +0900, Florian Gross wrote: > Hal Fulton wrote: > > >For example, I'll name this method "action"; suppose that in > >general, it just calls do_this and do_that. > > > > def action > > do_this > > do_that > > end > > > >But now suppose we enable things like a debug mode and a > >trace mode and logging and a configurable delay and such: > > > > def action > > STDERR.puts "Entering action" if @trace > > STDERR.puts "before do_this: foo = #@foo" if @debug > > @log.puts "#{Time.now}: Useful info" if @log > > sleep(@delay) if @delay > > do_this > > STDERR.puts "Returned from do_this" if @trace > > STDERR.puts "after do_this: foo = #@foo" if @debug > > @log.puts "#{Time.now}: More useful info" if @log > > do_that > > STDERR.puts "Returned from do_that" if @trace > > STDERR.puts "after do_that: foo = #@foo" if @debug > > @log.puts "#{Time.now}: Still more useful info" if @log > > end > > > >Here we've added ten if-statements. If #action is called > >frequently, performance will degrade even if these special > >attributes are not set. > > Maybe something like this will work reasonably? > > def initialize > @action_hooks = Hash.new do |hash, method| > hash[method] = Hash.new do |type_hash, type| > type_hash[type] = Array.new > end > end > end > > def call_hook(method, type, *more) > @action_hooks[method][type].each { |hook| hook.call(*more) } > end > > def register_hook(method, type, &block) > @action_hooks[method][type] << block > end > > def action > call_hook(:action, :before_do_this) > do_this > call_hook(:action, :before_do_that) > do_that > call_hook(:action, :before_end) > end > > I suppose that someway it could be factored out to a reusable Mix-In. I'm totally new to ruby, but it seems like blocks are the right way to go for this. Maybe something like this: --------------------------------------------------------- def do_this print "this" + "\n" end def do_that print "that" + "\n" end def hook yield end action = "trace" def hook print "hooked" + "\n" yield end if action == "trace" hook {do_this} hook {do_that} -- - Adam ----- http://www.adamfields.com