From: Mauricio Fernandez Date: 2006-07-09T17:15:01+09:00 Subject: Re: instance_exec On Sun, Jul 09, 2006 at 03:09:52PM +0900, ara.t.howard@noaa.gov wrote: > >Mauricio Fernandez's looks better though --think I'll have to rip it > >for Facets ;-) > > i just came across a bug in it (it's not re-entrant) - here's the fix: > [#instance_exec implementation] The example you gave does work with my implementation too: RUBY_VERSION # => "1.8.5" RUBY_RELEASE_DATE # => "2006-06-24" class Object module InstanceExecHelper; end include InstanceExecHelper def instance_exec(*args, &block) mname = "__instance_exec_#{Thread.current.object_id.abs}_#{object_id.abs}" InstanceExecHelper.module_eval{ define_method(mname, &block) } begin ret = send(mname, *args) ensure InstanceExecHelper.module_eval{ remove_method(mname) } rescue nil # ========== # thx to this end ret end end a = [] a.instance_exec 42 do |x| instance_exec x do |y| push y p size end end a # => [42] a.size # => 1 # >> 1 I had actually a test for that (see test_instance_exec_nested below). Do you have any additional assertions handy? (So far test_instance_exec_with_frozen_obj fails in all the other implementations I've seen.) require 'test/unit' class TestInstanceEvalWithArgs < Test::Unit::TestCase def test_instance_exec # Create a block that returns the value of an argument and a value # of a method call to +self+. block = lambda { |a| [a, f] } assert_equal [:arg_value, :dummy_value], Dummy.new.instance_exec(:arg_value, &block) end def test_instance_exec_with_frozen_obj block = lambda { |a| [a, f] } obj = Dummy.new obj.freeze assert_equal [:arg_value, :dummy_value], obj.instance_exec(:arg_value, &block) end def test_instance_exec_nested i = 0 obj = Dummy.new block = lambda do |arg| [arg] + instance_exec(1){|a| [f, a] } end # the following assertion expanded by the xmp filter automagically from: # obj.instance_exec(:arg_value, &block) #=> assert_equal([:arg_value, :dummy_value, 1], obj.instance_exec(:arg_value, &block)) end end -- Mauricio Fernandez - http://eigenclass.org - singular Ruby