Does instance_eval passes self as block argument?


#1

Ruby’s documentation of instance_eval shows the “signature” of
instance_eval as:

obj.instance_eval {| | block } => obj

I assume that the block should not take any argument. However, if I
write the following code:

class A
def sayhello(who)
puts “hello #{who}: #{object_id}”
end
end

A.new.instance_eval do |who|
sayhello(“me”)
who.sayhello(“who”)
end

it prints “hello me: -605850598” then “hello who: -605850598”

Is is guaranteed to work??

blambeau


#2

Ok, it works in Ruy 1.8.7 but not in Ruby 1.9.

Is there another way to do so?

blambeau


#3

LAMBEAU Bernard schrieb:

end

blambeau

should be, because it’s documented. Not in the code-example but in the
text:
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.


#4

Jan-Erik R. schrieb:

should be, because it’s documented. Not in the code-example but in the
text:
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.

oh…sorry. I missunderstood the documentation. Instead of using a
block-parameter you can use “self” directly.


#5

obj.instance_eval {| | block } => obj

I don’t interpret it that way: it only states that self is obj inside
the block. The documentation says nothing about block arguments.

I would like something like this:

obj.instance_eval {| who| block } => obj

where who ==self == obj.

blambeau


#6

LAMBEAU Bernard wrote:

obj.instance_eval {| | block } => obj

I don’t interpret it that way: it only states that self is obj inside
the block. The documentation says nothing about block arguments.

I would like something like this:

obj.instance_eval {| who| block } => obj
where who ==self == obj.

You can build that yourself.

class Object
def my_instance_eval(&blk)
instance_eval { blk[self] }
end
end

obj = “”
obj.my_instance_eval { |who| p who }


#7

LAMBEAU Bernard wrote:

I’m not sure that what I want makes sense because I’ve got self inside
the block, but if anyone knows how to make this code working in Ruby
1.9, I’m still interested.

class A
def doit(&block)
instance_eval(&block)
end
def sayhello(who)
puts “hello #{who}: #{object_id}”
end
end

A.new.doit do |who|
sayhello(“me”)
who.sayhello(“who”)
end

#=>
hello me: 35747370
hello who: 35747370


#8

Sorry but it does not work:

class A
def doit(&block)
instance_eval { block[self] }
end
def sayhello(who)
puts “hello #{who}: #{object_id}”
end
end

A.new.doit do |who|
sayhello(“me”)
who.sayhello(“who”)
end

in block in <main>': undefined methodsayhello’ for main:Object
(NoMethodError)

It seems that the block is not executed in the context of A.new anymore.

I’m not sure that what I want makes sense because I’ve got self inside
the block, but if anyone knows how to make this code working in Ruby
1.9, I’m still interested.

blambeau


#9

LAMBEAU Bernard wrote:

Works under Ruby 1.8.x, not with ruby 1.9.0 (I did not try with Ruby
1.9.1, which is more stable but not available yet under Ubuntu).

The only difference is the ‘who’ block parameter which is nil in 1.9.
If you really want that, this works on both 1.8 and 1.9:

class A
def doit(&block)
if RUBY_VERSION >= “1.9.0”
instance_exec(self, &block)
else
instance_eval(&block)
end
end
def sayhello(who)
puts “hello #{who}: #{object_id}”
end
end

A.new.doit do |who|
sayhello(“me”)
who.sayhello(“who”)
end


#10

Works under Ruby 1.8.x, not with ruby 1.9.0 (I did not try with Ruby
1.9.1, which is more stable but not available yet under Ubuntu).

Did-you try under Ruby 1.9.1 ?

blambeau