Zach Dennis said:
Also with the with block being how Jamis Buck and David A. Black posted
it works nice with methods as well.
def talk
puts "i'm talking"
end
def Test
def test
puts "i'm testing"
end
end
t = Test.new
with t do
talk
test
end
'talk' is called correctly because it is in the current scope of the
*with* block and 'test' is called correctly because it exists on object
't'.
The above works, but some very similar code is broken ... For example:
class Test
def test
puts "i'm testing"
end
end
class Dog
def talk
puts "i'm talking"
end
def testing_dog
talk # Class Dog#talk
t = Test.new
with t do
test # Calls Test#test
talk # ERROR: undefined local variable or method `talk'
end
end
end
This is because the second call to talk is not evaluated in the lexical
scope of the calling object Dog, but within the scope of the Test object.
Dog#talk exists, but Test#talk does not. (Your example missed the problem
by putting +talk+ into the global scope.
There is an awkward work around. First write +with+ like this:
module Kernel
def with(obj, &block)
obj.instance_eval { @self = eval("self", block) }
obj.instance_eval &block
end
end
Then reference Dog#talk like this ...
class Dog
def talk
puts "i'm talking"
end
def testing_dog
talk # Class Dog#talk
t = Test.new
with t do
test # Calls Test#test
@self.talk # Calls Dog#talk
end
end
end
···
--
-- Jim Weirich jim@weirichhouse.org http://onestepback.org
-----------------------------------------------------------------
"Beware of bugs in the above code; I have only proved it correct,
not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)