如何确定开始块的值?

ste*_*ang 5 ruby expression block

根据The Ruby Programming Language p.164.

如果begin语句不传播异常,则该语句的值是最后一个表达式的值的评估begin,rescueelse条款.

但是我发现这个行为与begin块以及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
Run Code Online (Sandbox Code Playgroud)

输出是:

"I am in the else statement"
"I will be always executed"
"The END of begin block"
"I am in the else statement"
[Finished]
Run Code Online (Sandbox Code Playgroud)

value被评估的其他条款.这是不一致的行为,因为ensure子句是最后执行的语句.

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

jtb*_*des 4

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

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

所以要么是section rescue,要么是else尝试完section后才会执行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"
Run Code Online (Sandbox Code Playgroud)

但:

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"
Run Code Online (Sandbox Code Playgroud)