Bindings and Context

Hi,
I’m still really confused about Ruby Closures.

At first I thought closures are just blocks who “remember” the context
that they were defined in (so that they can refer to local variables and
methods)

And then I discovered instance_eval (which changes the context that a
block is evaluated in).

When you use instance_eval you can’t call local methods anymore
(because, the scope has changed, and those methods aren’t local
anymore).

But how come I can still use local variables?

myStr = "myString"
o = Object.new
o.instance_eval do
  @str = myStr    # <- why does this still work?
  def method
    puts @str
  end
end

So are local variables sort of an exception to instance_eval? And in the
above example, how come it won’t work anymore if I change myStr into an
instance variable @myStr?

Thanks a lot for helping
-Patrick

PS: Is there a detailed document I can read about OO languages? I come
from Java and I’m feeling a little lost amidst all these advanced OO
features.

On Monday 11 August 2008, Patrick Li wrote:

When you use instance_eval you can’t call local methods anymore
puts @str
end
end

So are local variables sort of an exception to instance_eval? And in the
above example, how come it won’t work anymore if I change myStr into an
instance variable @myStr?

instance_eval doesn’t change scope. Its only effect is to change the
value of
the special local variable self. This explains why you can’t access
instance
variables anymore: with self changed, the instance variables are
instance
variables of the new self (that is, the receiver of instance_eval). The
same
is true for instance methods. Local variables, on the other hand, are
unaffected by the change of self and so you can still use them.

I hope this helps

Stefano

Ah. okay.
That really helps.

So is this a correct interpretation?

Every block/closure has an associated binding.

The binding can be loosely described as
-a list of local variables
-and self.

Calls to instance variables are shorthand for “self.@myInstanceVariable
and calls to instance methods are shorthand for “self.myInstanceMethod”

Does that sound alright?
-Cuppo

PS: You’ve really helped me out a lot recently Stefano. Thanks a lot.

On Monday 11 August 2008, Patrick Li wrote:

Ah. okay.
That really helps.

So is this a correct interpretation?

Every block/closure has an associated binding.

The binding can be loosely described as
-a list of local variables
-and self.

Yes, I think so

Calls to instance variables are shorthand for “self.@myInstanceVariable
and calls to instance methods are shorthand for “self.myInstanceMethod”

Does that sound alright?

that’s perfectly correct for calls to instance methods. For instance
variables, it’s true only conceptually, since ruby doesn’t allow to call
them
thay way.

Stefano

Thank you Stefano.
That clears up a lot of my misconceptions.
-Patrick

On 11.08.2008 17:09, Patrick Li wrote:

So is this a correct interpretation?

Every block/closure has an associated binding.

The binding can be loosely described as
-a list of local variables
-and self.

Yep.

Calls to instance variables are shorthand for “self.@myInstanceVariable
and calls to instance methods are shorthand for “self.myInstanceMethod”

Yes, apart from access control:

robert@fussel ~
$ ruby -e ‘class F;private;def x;puts 111;end
end;f=F.new;f.instance_eval { x };f.x’
111
-e:1: private method `x’ called for #<F:0x1002eef4> (NoMethodError)

“private” disallows method invocation with explicit receiver.

Kind regards

robert