Некоторые классы исключений, например Ошибка , не может обрабатывать управление потоком из блоков try / catch. Это приводит к тонким ошибкам:
use strict; use warnings;
use Error qw(:try);
foreach my $blah (@somelist)
{
try
{
somemethod($blah);
}
catch Error with
{
my $exception = shift;
warn "error while processing $blah: " . $exception->stacktrace();
next; # bzzt, this will not do what you want it to!!!
};
# do more stuff...
}
Обходной путь - использовать переменную состояния и проверять ее вне блока try / catch, что для меня выглядит ужасно, как вонючий код n00b.
Две другие "ошибки" в Error (оба из которых вызвали у меня горе, поскольку их ужасно отлаживать, если вы не сталкивались с этим раньше):
use strict; use warnings;
try
{
# do something
}
catch Error with
{
# handle the exception
}
Выглядит разумно, верно? Этот код компилируется, но приводит к причудливым и непредсказуемым ошибкам. Проблемы:
use Error qw(:try)
был опущен, поэтому блок try {}...
будет неправильно обработан (вы можете увидеть или не увидеть предупреждение, в зависимости от остальной части вашего кода)
- отсутствует точка с запятой после блока catch! Неинтуитивно, поскольку блоки управления не используют точки с запятой, но на самом деле
try
является вызовом прототипа .
О да, это также напоминает мне, что, поскольку try
, catch
и т. Д. Являются вызовами методов, это означает, что стек вызовов в этих блоках будет не таким, как вы ожидаете. (На самом деле есть два дополнительных уровня стека из-за внутреннего вызова внутри Error.pm.) Следовательно, у меня есть несколько модулей, заполненных шаблонным кодом, подобным этому, который просто добавляет беспорядок:
my $errorString;
try
{
$x->do_something();
if ($x->failure())
{
$errorString = 'some diagnostic string';
return; # break out of try block
}
do_more_stuff();
}
catch Error with
{
my $exception = shift;
$errorString = $exception->text();
}
finally
{
local $Carp::CarpLevel += 2;
croak "Could not perform action blah on " . $x->name() . ": " . $errorString if $errorString;
};