Использование однострочного условия с требованием/спасением

Я хочу избежать ошибки, если require не удалось.

Я могу сделать это с помощью:

begin
  require 'unexisting_script' 
rescue LoadError
end

Я попытался сделать то же самое с однострочным условием:

require 'unexisting_script' rescue LoadError

и получаю ошибку no such file to load -- unexisting_script (LoadError)

С другими исключениями/командами у меня нет проблем с однострочным спасением, это работает:

1 / 0 rescue ZeroDivisionError

Я также пытался заключить команду в скобки, но безуспешно:

(require 'unexisting_script') rescue LoadError

Я могу поместить все в одну строку с помощью ;:

begin require 'unexisting_script'; rescue LoadError; end

а мне все равно интересно, почему самая короткая версия не работает.

Я нашел несколько связанных вопросов, но ни в одном из них не упоминается проблема с требованием и спасением:

Мой вопрос:

Могу ли я использовать rescue в однострочном условии с require? Если да: как? Если нет: Почему?


person knut    schedule 12.11.2013    source источник
comment
возможный дубликат Действительно ли модификатор оператора спасения Ruby не работаете с требованием? - Но я оставляю вопрос открытым, я думаю, что вопрос имеет другую цель.   -  person knut    schedule 12.11.2013


Ответы (1)


Вы не можете указать класс ошибки, когда используете rescue в нотации postfix/oneliner. Что означает rescue LoadError или rescue ZeroDivisionError, так это то, что он спасет (подкласс) StandardError и в таком случае оценит LoadError или ZeroDivisionError, что не имеет никакого эффекта. Поскольку ZeroDivisionError является подклассом StandardError, он был захвачен, а LoadError - нет, и он не был захвачен.

Кстати, я не могу придумать вариант использования, когда вы хотите не вызывать ошибку, когда требуемый файл не существует. Обязательные файлы являются зависимостями, и если запросить их не удастся, то программа все равно не будет корректно работать. Я чувствую запах кода в том, что ты делаешь. Когда сбой при загрузке файла не приводит к сбоям в работе программы, обычно в этом случае следует использовать load вместо require.

person sawa    schedule 12.11.2013
comment
Для использования: Моя программа использует библиотеку для экспорта в специальный формат. Если он недоступен, я выдаю сообщение Формат экспорта XY не поддерживается, но только если кто-то его попросит. В моем особом случае я не ожидаю, что этот конкретный формат экспорта кому-либо понадобится, если соответствующая библиотека недоступна. В качестве альтернативы я мог бы заранее проверить, установлена ​​​​ли библиотека, но я думаю, что это больше работы, поскольку просто игнорирует ошибку загрузки. - person knut; 12.11.2013
comment
@sawa: Иногда это необходимо для поддержки разных альтернативных библиотек с похожими API. например (при использовании Ruby 1.8) fastcsv и csv. Если один недоступен, просто используйте другой. Другой пример использования — библиотеки JSON, например, в multi_json. . - person Holger Just; 12.11.2013
comment
Кнут и Хольгер, я вижу. В этом есть смысл. - person sawa; 12.11.2013
comment
О, я только недавно нашел это обсуждение. Я помню, как обсуждал это с Sawa на официальном баг-трекере. :) Мой вариант использования похож на knut, но больше мне нужно оставаться гибким и указывать более слабые зависимости - вещи, которые МОГУТ иметь пользователи, но которые могут быть не жизненно важными. Поскольку я использую множество таких требований, мне также нужно сделать это коротким. Предложение begin/rescue слишком длинное; так как я разбиваю свой код, мне нужно 5 строк кода для него. спасать nil на той же строке или что-то еще, тоже не элегантно; кстати, require() используется НАМНОГО чаще, чем load() в целом. - person shevy; 30.08.2020