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

E

Erik Veenstra

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.erikveen.dds.nl/

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

# 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

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

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,534
Members
45,007
Latest member
OrderFitnessKetoCapsules

Latest Threads

Top