`возврат` в основной среде - PullRequest
2 голосов
/ 16 апреля 2019

Когда я запускаю следующее в основной среде в 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

1 Ответ

3 голосов
/ 16 апреля 2019

Возвращение верхнего уровня было добавлено в качестве функции в ruby ​​2.4.0: https://bugs.ruby -lang.org / Issues / 4840

Он никогда не упоминался в объявлении о выпуске , но вы можете увидеть его в списке "языковых изменений" в более подробном новостном сообщении .

Если вы запустите файл, который содержит return "foo" в версии ruby ​​< 2.4.0, вы действительно увидите ошибку вроде:

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

Предполагаемый вариант использования (как вы можете видеть из приведенной выше ссылки) был для "отмены require" - например, если файл зависит от платформы, например:

require "test/unit"

return unless /mswin|cygwin|mingw|bccwin/

# ...

Было много дискуссий и споров по поводу предложенного синтаксиса и поведения; но выбранную реализацию лучше всего понять, прочитав контрольные примеры реализации :

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».

...