When I run the following in the main environment in irb or pry,
return "foo"
I get:
LocalJumpError: unexpected return
which is expected. But when I write this code in a separate file foo.rb
, and do:
$ ruby foo.rb
in the console, it terminates without any error message.
What is happening in the latter case?
I thought a raised error might be silently disposed with, and tried the following in a separate file:
begin
return "foo"
rescue Exception => e
p e
end
and executed it from the console, but this also resulted in no error.
When I put the code in an environment such as a module, it returns the error:
module A
return "foo" # >> Invalid return in class/module body
end
Top-level return was added as a feature in ruby 2.4.0: https://bugs.ruby-lang.org/issues/4840
It was never mentioned in the release announcement, but you can see it listed under the "language changes" in the more detailed news post.
If you run a file which contains return "foo"
in ruby version < 2.4.0
, you will indeed see an error like:
foo.rb:1:in `<main>': unexpected return (LocalJumpError)
The intended use case (as you can see from the above link) was for "cancelling a require
" - e.g. if the file is platform-specific, such as:
require "test/unit"
return unless /mswin|cygwin|mingw|bccwin/
# ...
There was much discussion and debate over proposed syntax and behaviour; but the chosen implementation can perhaps be best understood by reading the implementation's 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
Since writing return
inside a REPL like pry
is not at the "top level", this results in a LocalJumpError
instead of the above special behaviour for "top-level return
".