如何更改 lambda 的上下文?

How do I change the context of lambda?

如果您 运行 下面的代码会出错。

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 的上下文中 运行ning。所以它找不到方法def hi。我无法弄清楚如何在 class C 的情况下将其设置为 运行。

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

例如:

filter_clause("value", ->{ hi })

这可能吗?

不确定我说的是否有道理。

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

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

你很接近。如果您希望 lambda(/block,真的)在 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