我正在尝试编写一个可以捕获代码块并随后更改范围/闭包中的变量的类。
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>
答案 0 :(得分:0)
作为答案,即使我不确定它会有所帮助,因为评论中没有空格。看起来您可以使用特定绑定运行eval,例如使用当前绑定,在
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
是当前环境。