From: "Ara.T.Howard" Date: 2005-07-20T04:11:05+09:00 Subject: Re: Instance Eval of a Proc On Wed, 20 Jul 2005, Jacob Fugal wrote: > On 7/19/05, Daniel Brockman wrote: >> "Ara.T.Howard" writes: >> >>> the behaviour of Foo.method(:show_name) does exactly as >>> advertised - binding the method to the class Foo along >>> with that notion of self and instance vars. >> >> That is not in dispute. >> >>> so the binding of self for the duration of instance_eval >>> is definitely working >> >> Wait, wait, wait... timeout! >> >> Isn't the whole point of 'instance_eval' to change the >> binding of 'self'? > > Indeed. "Fighting ri with ri", we have from ri Object#instance_eval: > > Evaluates a string containing Ruby source code, or the given block, > within the context of the receiver (_obj_). In order to set the > context, the variable +self+ is set to _obj_ while the code is > executing, giving the code access to _obj_'s instance variables. > > So, according to documentation, instance_eval should set +self+ to > _obj_ while the code is executing. However, this binding doesn't > happen if there's already a binding for self. Question is, should it? > If so, there's a bug. If not, the documentation needs to reflect that. the docs are consistent, let me show it another way: harp:~ > cat a.rb class C # # this operates similarly to 'method' # def C::self_boxed self.instance_eval{ self } end end a = Array::new h = Hash::new a.instance_eval{ p [self, C::self_boxed] } h.instance_eval{ p [self, C::self_boxed] } harp:~ > ruby a.rb [[], C] [{}, C] this is similar to the way Class::method works - self has already been over-ridden. so in a case like obj = Object::new class C; end obj.instance_eval{ C::method('some_method').to_proc.call } then we have the case where 'self' is first swapped to 'obj' in order to call a block that then swaps 'self' for 'C'. so no matter how we wrap C::method('some_method').to_proc.call we will always find 'self' == C when we call the proc returns off of the Method object which wraps 'some_method'. that's because it works in a way roughly similar to 'self_boxed' in that it's already set up a layer of self swap'ing. one more example: harp:~ > cat a.rb a = 'a' b = 'b' la = lambda{ a.instance_eval{ self } } lb = lambda{ b.instance_eval{ [la(), self] } } p lb() harp:~ > ruby a.rb ["a", "b"] so you can't override self in a block that overrides self and Class#method is just that kind of method. uggh that's confusing. ;-) cheers. -a -- =============================================================================== | email :: ara [dot] t [dot] howard [at] noaa [dot] gov | phone :: 303.497.6469 | My religion is very simple. My religion is kindness. | --Tenzin Gyatso ===============================================================================