当我将lambda传递给instance_eval
作为块时,它似乎传递了一个额外的参数:
lamb = -> { puts 'hi' }
proc = Proc.new { puts 'hi' }
instance_eval(&lamb)
# >> ArgumentError: wrong number of arguments (given 1, expected 0)
# from (irb):5:in `block in irb_binding'
# from (irb):7:in `instance_eval'
instance_eval(&proc)
# => hi
instance_exec(&lamb)
# => hi
为什么会这样?请注意,此问题与lambda为什么会引发错误无关。这是众所周知的。问题在于为什么instance_eval
发送接收者的self
作为参数。不需要它,并且令人困惑。而且AFAIK没有记录。
This有帮助,但没有解释为什么红宝石会这样做。 instance_eval
的重点是将self
设置为接收者;为什么还要通过将self
传递给proc来混淆事物呢?
答案 0 :(得分:3)
来自文档
对于使用lambda或->()创建的proc,如果 错误数量的参数通过多个传递给Proc 参数。对于使用Proc.new或Kernel.proc创建的proc,额外 参数会被静默丢弃。
在您的情况下,lamb
和proc
都用一个参数调用了
From the docs of instance_eval
给instance_eval一个块时,obj也作为 阻止的唯一论点
instance_eval
是BasicObject
类的方法,可以在实例中调用。因此,例如,给定的块将可以访问私有方法。
class Test
def call
secret_number + 100
end
private
def secret_number
42
end
end
test = Test.new
show_secret = -> (obj) { puts secret_number }
test.instance_eval(&show_secret) # print 42
没有当前上下文的实例self
将作为参数传递。我认为instance_eval
的设计目的是为了在对象内调用它。
From the docs of instance_eval
为了设置上下文,将变量self设置为obj,而将 代码正在执行,使代码可以访问obj的实例变量 和私有方法。