Ruby block, procs and instance_eval
The difference is that a.instance_eval b
is passing b
as a regular argument to instance_eval, whereas a.instance_eval &b
is passing it as a block. Those are two different things.
Consider this method call:
obj.foo(bar) do |x|
stuff(x)
end
That invokes the method foo
with one regular argument (bar
) and one block argument (do |x| stuff(x) end
). In the method definition, they're distinguished by prefixing &
to the block parameter:
def foo(arg, &block)
And if you wish to pass a variable expression instead of a literal block, that is likewise accomplished by prefixing & to the expression (which should yield a Proc).
If you pass an argument with no &
, it goes in the arg slot instead of the block slot. It doesn't matter that the argument happens to be an instance of Proc. The syntax dictates how it is passed and treated by the method.
It's because instance_eval accepts a string to eval or a block. instance_eval(&block)
is passing your block
as a block to instance_eval.
All you have to do for your first example to work is this:
>> a.instance_eval &b #=> "SOME STRING"
The reason is that instance_eval
needs either a string or a block and the ampersand provides the latter.