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
selfis 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