Is Try:: Tiny по-прежнему рекомендуется для обработки исключений в Perl 5.14 или новее?

Консенсус сообщества Perl, похоже, заключается в том, что Try::Tiny является предпочтительным способом обработки исключений.

Perl 5.14 (это версия, которую я использую) кажется, решает проблемы с помощью eval что Try::Tiny адреса. Будет ли Try::Tiny предоставлять какие-либо льготы для меня?

Ответ 1

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

Практически, однако, люди используют die для отказа сигнала. Некоторые скажут, что вы можете die ссылаться и возвращать объекты ошибки, но для этого вам не нужно die. У нас есть объекты, поэтому мы должны использовать всю мощь объектов:

 sub some_sub {
    ...
    return Result->new( error => 1, description => ... ) if $something_went_wrong;
    return Result->new( error => 0, ... );
    }

 my $result = some_sub( ... );
 if( $result->is_error ) { ... };

Это не связано с глобальными переменными, действием на расстоянии, головными болями или требует специальных специальностей. Вы создаете крошечный класс Result или все, что вы хотите назвать, чтобы обернуть ваши возвращаемые значения, чтобы у вас были структурированные данные, а не единичные значения без идентификации. Там больше не интересно, что означает возвращаемое значение. Это undef реальное значение или указание сбоя? Является ли возвращаемое значение хорошим, если оно определено или оно верно? Ваш объект может рассказать вам об этом. И вы можете использовать один и тот же объект с die. Если вы уже используете объект с die и используете его как возвращаемое значение, очень мало рекомендовать все лишние вещи, которые вы должны сделать, чтобы терпеть [email protected].

Я больше об этом говорю в "Возвращать объекты ошибки вместо исключения исключений"

Однако я знаю, что вы не можете помочь другим людям, поэтому вам все равно придется притворяться, что у Perl есть исключения.

Ответ 2

Это всегда был случай личных предпочтений. Вы предпочитаете

my $rv;
if (!eval { $rv = f(); 1 } ) {
   ...
}

или

my $rv = try {
   f();
} catch {
   ...
};

Но имейте в виду, что последний использует anon subs, поэтому он беспорядок с return, а также next и тому подобное. Try:: Tiny try-catch вполне может оказаться намного сложнее, поскольку вы добавляете каналы связи между блоком catch и за его пределами.

Самый лучший случай (самый простой) сценарий для возврата в исключение - если $rv всегда истинно, когда нет исключения. Он будет выглядеть следующим образом:

my $rv;
if ($rv = eval { f() }) {
   ...
   return;
}

против

my $rv = try {
   f();
} catch {
   ...
};

if (!$rv) {
   return;
}

Вот почему я использовал TryCatch вместо Try:: Tiny, чтобы я использовал такие модуль.

Изменение на Perl просто означает, что вы можете сделать if ([email protected]) снова. Другими словами,

my $rv;
if (!eval { $rv = f(); 1 } ) {
   ...
}

можно записать

my $rv = eval { f() };
if ([email protected]) {
   ...
}

Ответ 3

Если ничего другого, Try::Tiny по-прежнему остается синтаксическим сахаром. Если вы хотите что-то немного более тяжеловесное, там также TryCatch, который решает некоторые проблемы, связанные с тем, что предложения в Try::Tiny являются подпрограммами (например, что return не оставляет закрывающей функции).

Ответ 4

Try::Tiny - легкий и легкий. Слишком легко. У нас было две проблемы:

  • анонимный - всегда были проблемы с оператором < return "внутри
  • ловить всегда и все

Итак, я внес некоторые изменения в Try::Tiny, что помогает нам. Теперь мы имеем:

try sub {},
catch 'SomeException' => sub {},
catch [qw/Exception1 Exception2/] => sub {},
catch_all sub {};

Я знаю - этот синтаксис немного экзотичен, но благодаря очевидному "sub" наши программисты теперь знают, что оператор "return" выходит из обработчика исключений, и мы всегда ловим только те исключения, которые хотим поймать:)

Ответ 5

Либо выполните:

local [email protected];
eval { … }

..., чтобы предотвратить изменение влияния [email protected]на глобальную область видимости или использование Try:: Tiny.

Синтаксически бывают ситуации, когда я предпочитаю один или другой.