首页 > 解决方案 > Ruby:使用 instance_eval(&lambda) 与 instance_eval { lambda.call } 时,lambda 内部的不同值

问题描述

我想调用一个 lambda 来改变它的自我价值。搜索它,我到达了instance_exec应该完成工作的地方。

但是,在研究一个示例 1 小时后,我发现这种行为我无法解释:

class Dummy

  class << self

    attr_accessor :my_lambda

  end

  self.my_lambda = proc { self }

  def test
    self.class.my_lambda.call
  end

  def test1
    instance_eval(&self.class.my_lambda)
  end

  def test2
    instance_eval { self.class.my_lambda.call }
  end

end

Dummy.new.test
=> Dummy # I was expecting this, returns the class, lexical scope (where `self` was defined)

Dummy.new.test1
=> #<Dummy:0x00007fe982f8b678> # I was expecting this, `self` changed to the receiver of `instance_eval`, which is the instance, so `self` returned the instance.

Dummy.new.test2
=> Dummy # I can't understand this, at all. Why isn't it the same as test1?

那么,为什么我们从instance_eval(&self.class.my_lambda)vs得到不同的结果instance_eval { self.class.my_lambda.call }呢?

另外,由于我们正在调用 Lambdas ...如果我将类级别变量更改为:

self.my_lambda = lambda { self }

然后 Dummy.new.test1 抛出一个异常ArgumentError: wrong number of arguments (given 1, expected 0),我也不明白为什么,因为我知道 lambdas 对参数数字很严格,但是当我们使用时我们没有通过任何instance_eval(&self.class.my_lambda)

标签: ruby

解决方案


令人惊讶的是,在写完这个长长的问题后,我如何在额外的一分钟内自己回答了这个问题。我需要一只橡皮鸭。无论如何。

我误会了instance_eval。它“在接收者(obj)的上下文中执行给定的块。”

所以,in 中的给定块#test2 instance_eval { self.class.my_lambda.call }确实是在self设置为实例的情况下执行的,但是lambda 仍然在其中调用,这不会改变它的自身。

但是,在 中#test1,& 符号&将 proc 更改为一个块,然后将其传递给instance_eval,因此执行self更改的是 proc 自己的主体。


推荐阅读