如何确定开始块的值?

根据The Ruby Programming Language p.164。

如果begin语句没有传播exception,则该语句的值是beginrescueelse子句中计算的最后一个表达式的值。

但是我发现这个行为与begin块以及else子句ensure子句一致

这是示例代码:

 def fact (n) raise "bad argument" if n.to_i  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] 

valuevalue else子句 。 这是不一致的行为,因为ensure子句是最后执行的语句。

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

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

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

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

这只是一个副作用, 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" 

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

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

请记住,在这种情况下,如果没有exception发生,则运行,并ensure无论exception或缺少exception都会运行。