This is a multi-part message in MIME format. ------ extPart_000_0079_01C31FF9.09646CC0 Content-Type: text/plain; charset so-8859-1" Content-Transfer-Encoding: 7bit "Hal E. Fulton" <hal9000 / hypermetrics.com> schrieb im Newsbeitrag news:096701c31fc3$4f78b3a0$0300a8c0 / austin.rr.com... > OK, I read Matz's blog entries as well as I could. > > One thing that occurs to me is that I don't really > want to distinguish between "before" and "after" > in an artificial way. > > Here's my tentative dream of how I'd like to do > this kind of thing in Ruby. (I'm using the keyword > 'prior' for lack of anything better right now.) > > <fantasy> > > class String > > define_hook(:length) do > puts "I'm calculating the length" > prior > end > > define_hook(:upcase) do > val rior > puts "I just did an upcase operation" > val > end > > define_hook(:reverse) do > puts "I'm about to do a reverse operation" > val rior > puts "I just did a reverse" > val > end > > end > > str abcde" > > x tr.length > puts x > > y tr.upcase > puts y > > z tr.reverse > puts z > > # Output: > # I'm calculating the length > # 5 > # I just did an upcase operation > # ABCDE > # I'm about to do a reverse operation > # I just did a reverse > # edcba > > </fantasy> That's no fantasy. Dreams come true... > Notes: > > 1. Obviously parameter-passing needs to be addressed. > 2. It would be nice to get around the return-value > problem (where have I seen this before? 'ensure'?) > 3. I've probably overlooked a lot of issues. Please > educate me (Matz, Guy, Dave, David, others...) Although not listed this bugged me. See what I came up with (attached). Cons: - 'this' had to be introduced since I found no way to rebind the proc (even if there were a way we had to deal with multiple concurrent invocations). The deeper reason for this problem is, that the block comes into existence in class context but should be evaluated in instance context later. - Argument lists have to be doubled for the block Pros: - It nearly looks like what you asked for. - Return values work reasonably. - It even works for nested invocations, i.e. recursion - It works with several instances in the call chain - You can exactly do what you put in <fantasy> Regards robert ------ extPart_000_0079_01C31FF9.09646CC0 Content-Type: application/octet-stream; name ook_test.rb" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename ook_test.rb" require 'hooks.rb' class String define_hook(:length) do puts "I'm calculating the length" prior end define_hook(:upcase) do val rior puts "I just did an upcase operation" val end define_hook(:reverse) do puts "I'm about to do a reverse operation" val rior puts "I just did a reverse" val end end str abcde" x tr.length puts x y tr.upcase puts y z tr.reverse puts z ------ extPart_000_0079_01C31FF9.09646CC0 Content-Type: application/octet-stream; name ooks.rb" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename ooks.rb" class Object private def prior thr hread.current ths hr[ :__hook_self ] sym hr[ :__hook_next ] raise "No more methods in chain" unless sym begin # puts '>>> nest' result hs.send( sym, *(thr[ :__hook_args ])) # puts '<<< unnest' return result ensure thr[ :__hook_next ] ym thr[ :__hook_self ] hs end end def this Thread.current[ :__hook_self ] end end class Module private def set_hook_proc( key, pr ) (@hook_procs || })[ key ] r end public def get_hook_proc( key ) (@hook_procs || })[ key ] end def define_hook( symbol, &block ) al enerate_hook_alias symbol set_hook_proc( al, proc &block ) x <-"EO_HOOK" alias #{al} #{symbol} def #{symbol}(*args) thr hread.current thr[ :__hook_self ] elf thr[ :__hook_args ] rgs thr[ :__hook_next ] #{al} #{self}.get_hook_proc( "#{al}" ).call( *args ) end EO_HOOK # puts x self.class_eval x # p @hook_procs end private def generate_hook_alias( symbol ) im nstance_methods count begin s __hook__#{symbol}_#{count}" count + end while im.include? s s end end ------ extPart_000_0079_01C31FF9.09646CC0--