主环境中的`return`

`return` in main environment

当我运行以下在主环境中irb或pry,

return "foo"

我得到:

LocalJumpError: unexpected return

这是预期的。但是当我在单独的文件 foo.rb 中编写此代码并执行以下操作时:

$ ruby foo.rb

在控制台中,它终止且没有任何错误消息。

后一种情况发生了什么?

我认为引发的错误可能会被静默处理,并在单独的文件中尝试了以下操作:

begin
  return "foo"
rescue Exception => e
  p e
end

并从控制台执行它,但这也没有导致错误。

当我将代码放在模块等环境中时,它 returns 错误:

module A
  return "foo" # >> Invalid return in class/module body
end

顶级 return 已作为功能添加到 ruby 2.4.0 中:https://bugs.ruby-lang.org/issues/4840

它从未在 release announcement, but you can see it listed under the "language changes" in the more detailed news post 中提及。

如果您 运行 一个包含 ruby 版本 < 2.4.0 的文件 return "foo",您确实会看到如下错误:

foo.rb:1:in `<main>': unexpected return (LocalJumpError)

预期用例(正如您从上面 link 中看到的那样)是针对 "cancelling a 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

因为在像 pry 这样的 REPL 中写入 return 不在 "top level",这导致 LocalJumpError 而不是上述 [=37] 的特殊行为=].