【问题标题】:How do I change the context of lambda?如何更改 lambda 的上下文?
【发布时间】:2015-06-13 20:08:31
【问题描述】:

如果你运行下面的代码,你会得到一个错误。

class C
  def self.filter_clause param_1
    puts param_1
    yield # context of this param is class B
  end

  def hi
    "hello"
  end
end

class B
  def self.filter(value, lambda)
    code = lambda { filter_clause(value, &lambda) }
    C.instance_exec(&code)
  end

  filter(:name, ->{ hi })
end

错误是

NameError: undefined local variable or method `hi' for B:Class
from (pry):17:in `block in <class:B>'

据我了解,原因是 lambda 在 class B 的上下文中运行。所以找不到方法def hi。我不知道如何让它在class C 的上下文中运行。

本质上,我希望能够注入在另一个接受参数和块的类中调用的方法。

例如:

filter_clause("value", -&gt;{ hi })

这可能吗?

不确定我是否有道理。

【问题讨论】:

  • 这个A类在哪里?
  • 抱歉删除了对 A 的引用。

标签: ruby lambda metaprogramming


【解决方案1】:

你已经接近了。如果您希望 lambda(/block, really) 在 C 实例的上下文中执行(因为 hi 是 C 上的实例方法),那么您需要实例化它,然后 instance_exec 上的块那个新实例:

class C
  def self.filter_clause param_1, &block
    puts new.instance_exec &block
  end

  def hi
    "hello"
  end
end

class B
  def self.filter(value, lambda)
    code = lambda { filter_clause(value, &lambda) }
    C.instance_exec(&code)
  end

  filter(:name, ->{ hi })
end

# => hello

【讨论】:

  • instance_execinstance_exec 内?有趣的预期:D 不管怎样,这是有效的 Ruby。
  • 这里有两个 lambda,它们都必须被反弹。我们不只是重新绑定同一个 lambda 两次。 code lambda 被反弹以在 C 上执行,而传递给 filter 的匿名 lambda 被反弹以在 C 的实例上执行。
  • 是的,但是其中一个上下文仍然没有使用。
  • 谢谢。我已将此标记为答案,尽管它不完全是我想要的。我不想更改 C.filter 的签名。我还有另一个更高层次的问题,这是我真正想要实现的。在 1 个问题中解释所有内容有点困难。 stackoverflow.com/questions/30819919/…
  • @Ryan-NealMes 您的其他问题已删除,但不是很清楚。您能否提供一个您实际尝试做的非伪代码示例?
【解决方案2】:

你反对将上下文传递到块中吗?如果没有,这样的事情会起作用:

class C
  def self.filter_clause param_1
    puts param_1
    yield self
  end

  def hi
    "hello"
  end
end

class B
  def self.filter(value, lambda)
    code = lambda { filter_clause(value, &lambda) }
    C.instance_exec(&code)
  end

  filter(:name, ->(klass){ klass.new.hi }) # "hello"
end

【讨论】:

  • 谢谢,但如果可能的话,我不想在调用过滤器时指定上下文。我已经设法获得了该工作的一个版本。感觉就像它使代码膨胀。我希望我能以某种方式让它推断出上下文。我可能会更新 def self.filter 方法中的上下文,但我不确定如何更改 def self.filter 中 lambda 的上下文。
猜你喜欢
  • 2019-08-27
  • 2013-05-03
  • 2019-01-11
  • 1970-01-01
  • 2020-02-03
  • 1970-01-01
  • 1970-01-01
  • 2012-03-03
  • 2017-02-06
相关资源
最近更新 更多