Ruby block, procs and instance_eval

brad picture brad · Jun 16, 2011 · Viewed 9.9k times · Source

I recently tried to do something akin to this:

a = "some string"
b = Proc.new{ upcase }
a.instance_eval b

Which gives the error:

TypeError: can't convert Proc into String

but this works:

def b(&block)
  "some string".instance_eval &block
end

b{ upcase }

A further look with this method:

def b(&block)
  "some string".instance_eval block
end

Yields the same Proc to String error.

So... my understanding of blocks is that they are just procs. But there's obviously something special about having this & ampersand...

Can someone explain this to me? Is it possible to convert a normal proc to be whatever it is that is special about this &block object?

edit

Just figured out my second question, prepend an & to the proc... that was easy, but WHAT is this really doing?

Answer

Michael Kohl picture Michael Kohl · Jun 16, 2011

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.