如何更改lambda的上下文?

时间:2015-06-13 20:08:31

标签: ruby lambda metaprogramming

如果您运行以下代码,则会收到错误。

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", ->{ hi })

这可能吗?

不确定我是否有意义。

2 个答案:

答案 0 :(得分:3)

你很亲密。如果你希望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

答案 1 :(得分: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