gpt4 book ai didi

ruby - 我可以根据 Ruby 中的 Binding 对象评估 block 吗?

转载 作者:数据小太阳 更新时间:2023-10-29 08:49:24 24 4
gpt4 key购买 nike

我试图将引发异常的上下文传递给 Exception 子类,以便使用此上下文生成信息性错误消息。我知道我可以将单个数据片段传递给异常,但我想知道如何传递和使用整个上下文。

我知道我可以使用 Kernel#binding 捕获上下文。类 Binding 的 Ruby 2.0 文档列出了一个方法:eval。这允许您在 Binding 捕获的上下文中评估 String。我想知道是否可以在绑定(bind)的上下文中评估 block 。我会按如下方式使用它:

class MyError < StandardError

def initialize(str: nil, context: nil)
@str = str; @context = context
super(str)
end

def to_s
@str ? @str : @context.**SOME_METHOD** { "Error: x == #{x}" }
end

end

x = 5
raise MyError.new(context: binding)

=> Error: x == #{5}

我已经为 SOME_METHOD 尝试了 instance_execinstance_eval,但都不起作用。有什么办法吗?或者,是否有某种原因表明从整个上下文而不是环境中的个别数据生成错误消息是个坏主意?

最佳答案

使用 eval(string, binding) 运行带有给定变量绑定(bind)的 Ruby 代码。对于您的情况,您可以重写 to_s 方法,如下所示:

def to_s
@str ? @str : eval('"Error: x == #{x}"', @context)
end

请注意,在将参数传递给 eval 之前,您需要使用 '"some_string"' 形式来防止字符串插值。

如果你想用一些绑定(bind)来评估 block ,你必须将 block 分配给一个变量,然后像 block.call 一样eval block 。现在您有两个绑定(bind)环境,一个用于变量 block,另一个用于 block 中的变量。由于Binding没有joincombine等方法,所以Kernel#eval似乎无法实现> 或 Binding#eval。此外,一个 block 在定义它的地方捕获它的绑定(bind)。当您调用 eval('block.call', some_binding) 时,它会忽略传入的绑定(bind)。

但是,您可以使用 Object#instance_eval 并以 instance_eval(&block) 的形式传递 block ,这将在类实例的绑定(bind)中评估 block 方法。因此,您可以使用捕获的上下文为 block 创建适当的绑定(bind)。

class BlockEnv
def initialize(context, &block)
# remove instance methods inherited from Object to minimize the impact
# remove this if unnecessary
BlockEnv.instance_methods
.reject{|m|
[:object_id, :call, :instance_eval, :method_missing].include?(m) ||
m.to_s !~ /^[a-z]\w*$/i }
.each do |m|
eval("undef :#{m}")
end
@context = context
@block = block
end
def call
self.instance_eval(&@block)
end
def method_missing(name)
eval(name.to_s, @context) rescue super
end
end

class MyError < StandardError
def initialize(str: nil, context: nil)
@str = str; @context = context
super(str)
end

def to_s
@str ? @str : BlockEnv.new(@context){ "Error: x == #{x}" }.call
end
end

x = 5
raise MyError.new(context: binding)

关于ruby - 我可以根据 Ruby 中的 Binding 对象评估 block 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17158973/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com