This is a multi-part message in MIME format.

------extPart_000_0079_01C31FF9.09646CC0
Content-Type: text/plain;
	charsetso-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;
	nameook_test.rb"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
	filenameook_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;
	nameooks.rb"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
	filenameooks.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--