For example, let's say I have
block = proc { |n| "#{downcase} #{n}" }
Now I want to evaluate that block in the scope of a String
, but pass that block a variable. I know how to do the first part:
"Foo".instance_eval(&block)
But how to also pass a variable to that block?
I tried
"Foo".instance_eval { block.call(3) }
But it didn't work, it wasn't in the scope of the String
.
Use instance_exec
instead:
instance_exec(arg...) {|var...| block } → obj
Executes 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. Arguments are passed as block parameters.
So this will make it go:
"Foo".instance_exec(3, &block)
and give you the 'foo 3'
that you desire.
The problem with this:
"Foo".instance_eval { block.call(3) }
is that self
will be "Foo"
inside { block.call(3) }
but not inside block
, block
will retain whatever self
was when block
was defined; there's nothing in block.call(3)
that forces a context so self
doesn't change. For example, given this:
class C
def m
proc { |n| "#{downcase} #{n}" }
end
end
c = C.new
"Foo".instance_eval { c.m.call(3) }
When the proc is called, self
will be c
because that's what self
was when the proc was defined (i.e. when m
was called). What self
is inside the instance_eval
block doesn't have any effect on self
inside the proc.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With