[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

object = watch(object){|x| "DO SOMETHING WITH X"}

Erik Veenstra

1/27/2006 2:10:00 PM

I did this lazy-evaluation exercise, a couple of days ago.
(Thanks, MenTaLguY!). Little modifications to that code result
in the library below. Sometimes, for debugging reasons, you
want to trace a variable. Which line of code does something
with my object? Where does that nil come from?

Instead of inserting a lot of debug statements, we could simply
"watch" the variable, without affecting the original behaviour
of the object:

object = watch(object){|x| "DO SOMETHING WITH X"}

Is it useful? Thoughts? Comments? Anything I overlooked?

Thanks.

gegroet,
Erik V. - http://www.erikve...

----------------------------------------------------------------

# EXAMPLE

require "watch"

arr = []

arr =
watch(arr) do |object, method, parms, timing|
if parms.include?(nil)
$stderr.puts caller[2..-1].reverse.inspect
end
end

arr << 123
arr << nil
arr << 234

p arr.class

----------------------------------------------------------------

# LIBRARY

module Watch
class WatchException < Exception
superclass.instance_methods(false).each do |method|
undef_method(method) unless method =~ /^__/
end

def initialize(exception)
@original_exception = exception
end

def exception
self
end

def method_missing(method_name, *parms, &block)
@original_exception.send(method_name, *parms, &block)
end
end

class Watch
instance_methods(true).each do |method|
undef_method(method) unless method =~ /^__/
end

def initialize(real_object, timing=:before, &block)
@real_object = real_object
@timing = timing
@block = block
end

def method_missing(method_name, *parms, &block)
go =
lambda do |timing|
begin
@block.call(@real_object) if
@block.arity == 1
@block.call(@real_object, method_name, parms) if
@block.arity == 3
@block.call(@real_object, method_name, parms, timing) if
@block.arity == 4
rescue Exception => e
raise WatchException.new(e)
end
end

go.call(:before) if @timing == :both or @timing == :before

res = @real_object.send(method_name, *parms, &block)

go.call(:after) if @timing == :both or @timing == :after

res
end
end
end

module Kernel
def watch(*parms, &block)
Watch::Watch.new(*parms, &block)
end
end

----------------------------------------------------------------