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


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

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

5 74

5 ответов:

мой ответ непопулярен, но я не думаю, что программисты 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 и используя его в качестве возвращаемого значения, очень мало, чтобы рекомендовать все дополнительные вещи, которые вы должны сделать, чтобы терпеть $@.

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

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

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

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

или

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

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

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

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

vs

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

if (!$rv) {
   return;
}

вот почему я бы использовал TryCatch вместо Попробовать: Крошечные если бы я использовал такой модуль.

изменение на Perl просто означает, что вы можете сделать if ($@) еще раз. Другими словами,

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

можно писать

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

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

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

  • аноним subs-всегда были проблемы с' внутри
  • ловить всегда и все

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

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

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

сделать:

local $@;
eval { … }

... чтобы предотвратить изменение $@ от влияния глобальной области, или использовать Try:: Tiny.

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