В Ruby, в какие структуры может быть вложен оператор `rescue`

В ruby ​​для обнаружения ошибки используется оператор rescue. обычно это утверждение происходит между begin и end. Можно также использовать оператор rescue как часть блока (do ... end) или метода (def ... end). Мой вопрос в том, какие другие структуры (петля, в то время как, если, ...), если таковые имеются, спасут гнездо внутри?


person John F. Miller    schedule 26.03.2010    source источник
comment
Блоки do ... end не могут быть восстановлены без явного указания begin ... end.   -  person Nick    schedule 25.02.2017
comment
Поскольку ruby 2.5 do ... end блоков можно спасти без явного указания begin ... end.   -  person pimpin    schedule 05.01.2021


Ответы (2)


Спасение можно использовать только в двух случаях:

  • Внутри блока begin ... end

    begin
      raise
    rescue 
      nil
    end
    
  • Как модификатор оператора

    i = raise rescue nil
    

Тела функций, модулей и классов (спасибо Йоргу) являются неявными блоками begin...end, поэтому вы можете спасать в любой функции без явных begin/end.

    def foo
      raise
    rescue
      nil
    end

Блочная форма принимает необязательный список параметров, указывающих, какие исключения (и потомки) rescue:

    begin
      eval string
    rescue SyntaxError, NameError => boom
      print "String doesn't compile: " + boom
    rescue StandardError => bang
      print "Error running script: " + bang
    end

При вызове встроенного в качестве модификатора оператора или без аргумента в блоке begin/end служба восстановления поймает StandardError и его потомки.

Вот документация 1.9 по rescue.

person klochner    schedule 26.03.2010
comment
Тела module и class также являются неявными блоками begin. - person Jörg W Mittag; 26.03.2010
comment
@ Jörg W Mittag: как и do ... end блоки и def ... end определения методов. Есть ли что-нибудь еще, что является неявным begin? while, case или if например? - person John F. Miller; 28.03.2010
comment
@john - делать... конец не является неявным началом... концом. - person klochner; 28.03.2010
comment
Я предлагаю добавить комментарий выше о том, что делать... конец ответа... это действительно то, что я искал. - person pedz; 26.07.2017
comment
Хотя это и не очень хорошо документировано, в ruby ​​2.5 rescue работает в обычных блоках do/end (хотя и не в линейных блоках {...}). зафиксировать - person Vigintas Labakojis; 18.02.2020

Как сказано в последнем комментарии ответ изменился по сравнению с Ruby 2.5.

Блоки do ... end теперь являются неявными блоками begin ... end; например тела модулей, классов и методов.

Встроенные блоки {...} по-прежнему не могут.

person pimpin    schedule 05.01.2021