【发布时间】: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 = -> { future_variable.upcase }不允许您在 lambda 后定义future_variable时使用l.call。是的,在这种情况下全局有效,但全局不好,mkey? -
我不清楚您希望它如何工作。
@scope_additions是一个散列,那么在评估块之前,目标是在块中创建与散列键同名的局部变量吗?我不确定这是否可能。 -
没错。范围添加应该合并到块的绑定中。