如何确定开始块的值?

时间:2012-03-13 15:59:21

标签: ruby expression block

根据The Ruby Programming Language第164页。

  

如果begin语句没有传播异常,那么该值   语句的评估的最后一个表达式的值   beginrescueelse条款。

但我发现这种行为与开始阻止以及 else子句确保子句一致。

以下是示例代码:

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子句是最后执行的语句。

有人可以解释开始区块内发生了什么吗?

3 个答案:

答案 0 :(得分:4)

我将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"

答案 1 :(得分:0)

我只是在这里猜测,但是因为确保块的目的是确定任何可能保持打开的资源(换句话说是清理),所以逻辑值应该是else的结果是有意义的声明。对我来说这是有意义的。

答案 2 :(得分:0)

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

请记住,如果没有例外,则else会运行,ensure将会运行,无论例外情况如何或缺少例外情况。