当我在irb或pry的主环境中运行以下内容时,
return "foo"
我明白了:
LocalJumpError: unexpected return
这是预料之中的。但是,当我在单独的文件foo.rb
中编写此代码时,并执行:
$ ruby foo.rb
在控制台中,它终止没有任何错误消息。
后一种情况发生了什么?
我认为可能会默默地处理引发的错误,并在单独的文件中尝试以下内容:
begin
return "foo"
rescue Exception => e
p e
end
并从控制台执行它,但这也导致没有错误。
当我将代码放在诸如模块的环境中时,它返回错误:
module A
return "foo" # >> Invalid return in class/module body
end
顶级返回作为ruby 2.4.0中的一个特性添加:https://bugs.ruby-lang.org/issues/4840
在release announcement中从未提及它,但你可以在更详细的news post中看到它列在“语言变化”下。
如果您在ruby版本return "foo"
中运行包含< 2.4.0
的文件,您确实会看到如下错误:
foo.rb:1:in `<main>': unexpected return (LocalJumpError)
预期的用例(从上面的链接可以看出)是“取消require
” - 例如如果文件是特定于平台的,例如:
require "test/unit"
return unless /mswin|cygwin|mingw|bccwin/
# ...
对提议的语法和行为进行了大量讨论和辩论;但是通过阅读实现的test cases,可能最好地理解所选择的实现:
def test_return_toplevel
feature4840 = '[ruby-core:36785] [Feature #4840]'
code = <<~'CODE'
return; raise
begin return; rescue SystemExit; exit false; end
begin return; ensure exit false; end
begin ensure return; end
begin raise; ensure; return; end
begin raise; rescue; return; end
return false; raise
return 1; raise
CODE
all_assertions(feature4840) do |a|
code.each_line do |s|
s.chomp!
a.for(s) {assert_ruby_status([], s)}
end
end
end
由于在像return
这样的REPL中写pry
不是“顶级”,这导致LocalJumpError
而不是上面的“顶级return
”的特殊行为。