【问题标题】:Changing the binding of a block更改块的绑定
【发布时间】:2014-08-05 15:32:36
【问题描述】:

我正在尝试编写一个可以捕获代码块并随后更改作用域/闭包中的变量的类。

class BlockCapture

  attr_reader :block

  def initialize(&block)
    @block = block
    @scope_additions = {}
  end

  def merge_into_scope(values = {})
    @scope_additions = @scope_additions.merge(values)
  end

  def mutated_block
    # some code that merges the scope additions into the binding
    # and returns the context
  end
end

captured_block = BlockCapture.new do
  future_variable.upcase
end

captured_block.block.call # This should trigger a NameError, as `future_variable` is not in scope.

captured_block.merge_into_scope(future_variable: "I was added to the scope")

captured_block.mutated_block.call # This should work
=> "I WAS ADDED TO THE SCOPE"

我不知道如何将变量合并到范围中。

我尝试在块变量上调用绑定方法,但它每次都返回一个新绑定,所以它似乎是原始块绑定的副本,而不是对原始块绑定的引用。

irb(main):078:0> capture.block.binding
=> #<Binding:0x007fa38292e398>
irb(main):079:0> capture.block.binding
=> #<Binding:0x007fa382925f18>
irb(main):080:0> capture.block.binding
=> #<Binding:0x007fa38291d908>

【问题讨论】:

  • 有趣。你确定你能做到吗?如果块是一个闭包,它应该在创建时刻的环境(范围)中工作。例如:l = -&gt; { future_variable.upcase } 不允许您在 lambda 后定义 future_variable 时使用 l.call。是的,在这种情况下全局有效,但全局不好,mkey?
  • 我不清楚您希望它如何工作。 @scope_additions 是一个散列,那么在评估块之前,目标是在块中创建与散列键同名的局部变量吗?我不确定这是否可能。
  • 没错。范围添加应该合并到块的绑定中。

标签: ruby lambda scope proc


【解决方案1】:

定位为答案,即使我不确定它是否会有所帮助,因为评论中没有空格。看起来您可以使用特定绑定运行 eval,例如使用当前绑定,定义 lambda 之后创建:

bind_lambda = -> (bind, x) { bind.eval x }
#=> #<Proc:0x007fec943b85e8@(pry):1 (lambda)>

第一次尝试以错误结束,正如预期的那样:

bind_lambda.call binding, 'future_var'
NameError: undefined local variable or method `future_var' for main:Object
from (pry):2:in `__pry__'

但是在声明了局部变量之后:

future_var = "here be dragons"
#=> "here be dragons"

我们可以到达:

bind_lambda.call binding, 'future_var'
#=> "here be dragons"

这是因为binding 是当前环境。

【讨论】:

  • 这很有趣,但并不是真正的解决方案。我需要这样做的原因是因为该块被传递到某个库,而该库在调用它时无法被指示传递参数。我无法更改库调用 lambda 的方式。
  • Ruby 2.1 中有一个方法Binding.local_variable_set - 我没试过,但看起来很有希望
  • 我试过了。问题是 my_proc.binding 显然返回了绑定的副本,而不是引用,而且我还没有找到将新绑定分配给 proc 的方法。
猜你喜欢
  • 2017-12-08
  • 2011-08-16
  • 1970-01-01
  • 2016-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多