【问题标题】:How is the value of a begin block determined?开始块的值是如何确定的?
【发布时间】:2012-03-13 15:59:20
【问题描述】:

根据The Ruby Programming Language p.164。

如果begin 语句没有传播异常,则值 语句的最后一个表达式的值beginrescueelse 子句。

但我发现这种行为与 begin block 以及 else 子句ensure 子句 一致。

示例代码如下:

def fact (n)
  raise "bad argument" if n.to_i < 1
end

value = begin
  fact (1)
rescue RuntimeError => e
  p e.message
else
  p "I am in the else statement"
ensure
  p "I will be always executed"
  p "The END of begin block"
end

p value

输出是:

"I am in the else statement"
"I will be always executed"
"The END of begin block"
"I am in the else statement"
[Finished]

value 被评估为 else 子句。这是不一致的行为,因为 ensure 子句 是最后执行的语句。

有人能解释一下 begin 块中发生了什么吗?

【问题讨论】:

  • "为最后执行的语句评估代码块"。这显然是一个错误的假设。
  • 抱歉,请使用更具体的陈述和参考进行更正。
  • 现在你自己回答了这个问题:“begin, rescue or else”其实是正确的顺序,所以这符合规范。
  • 所以您的意思是,规范应该被解释为“在 (order of) begin、rescue 或 else 子句中评估的最后一个表达式的值”?这里说得通。
  • 是的,这就是我对那句话的解释。

标签: ruby expression block


【解决方案1】:

我将begin/rescue/else/end 块的目标解释为:

  • 执行begin 部分中的代码,然后执行else 部分中的代码。
  • 如果begin 部分出现问题,请执行rescue 部分而不是else 部分。

所以任一rescue 部分或else 部分将在尝试begin 部分后执行;因此,其中一个将用作整个块的值是有道理的。

ensure 部分将始终被执行只是一个副作用。

val = begin
  p "first"; "first"
rescue => e
  p "fail"; "fail"
else
  p "else"; "else"
ensure
  p "ensure"; "ensure"
end

val # => "else"
# >> "first"
# >> "else"
# >> "ensure"

但是:

val = begin
  p "first"; "first"
  raise
rescue => e
  p "fail"; "fail"
else
  p "else"; "else"
ensure
  p "ensure"; "ensure"
end

val # => "fail"
# >> "first"
# >> "fail"
# >> "ensure"

【讨论】:

    【解决方案2】:

    我只是在这里猜测,但由于确保块的目的是完成任何可能保持打开状态的资源(换句话说就是清理),因此逻辑值应该是 else 的结果是有道理的陈述。对我来说,这是设计使然。

    【讨论】:

      【解决方案3】:

      在这种情况下,begin 块只是定义您可能想要进行异常处理的节的一种方式。

      请记住,在这种情况下,else 在没有异常发生的情况下运行,ensure 将运行而不管是否存在异常。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-07-21
        • 1970-01-01
        • 1970-01-01
        • 2021-12-27
        • 2014-11-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多