Just realized that instance_eval
yields self
as an argument to the associated block (except for a bug in the 1.9.2 version: http://www.ruby-forum.c
I just asked the same question here: Ruby lambda's proc's and 'instance_eval'
And after reading the answer and working through some code, I think I understand why ruby has this strange (IMHO) inconsistency.
It basically allows Symbol#to_proc
to work.
For example ["foo", "bar"].each(&:puts)
is short for [...].each { |x| puts x }
NOT
[...].each { self.puts }
So ruby also passes self as the first param to the proc, so basically the proc can either use self or its first param.
Since instance eval does not by definition explicitly pass params this is almost always invisible behavior.
The exception is when the proc is a lambda. This DOES NOT WORK:
2.4.1 :015 > foo = -> { puts 'hi' }
=> #
2.4.1 :016 > [1, 2, 3].each(&foo)
ArgumentError: wrong number of arguments (given 1, expected 0)
from (irb):15:in `block in irb_binding'
from (irb):16:in `each'
from (irb):16
So I think the only time this becomes a problem is when instance_eval is being used with some unknown value, where you don't know if the proc is a lambda or not. In this case you have to do it like this:
proc_var.lambda? ? instance_exec(&proc_var) : instance_eval(&proc_var)
Weird (to me) that ruby just does not do this under the hood for you.
but I guess you could make it so:
alias original_instance_eval instance_eval
def instance_eval(*args, &block)
block&.lambda? ? instance_exec(&block) : original_instance_eval(*args, &block)
end