Чем плох eval?!
В perl, как всем известно, имеется 2 варианта вызова функции eval. Строковый eval для компиляции и выполнения кода на лету и блочный eval.Нас интересует блочный eval.
Часто встречается такой вот код:
eval { # some code die "error"; # some code }; if ($@) { print "Error [$@] occured!"; }
Это вполне стандартный код, но есть ряд недостатков связанных и с использованием глобальной переменной $@.
Потенциальная проблема #1
Если кто-то локализировал переменную $@, то мы не сможем перехватить исключение. В этом коде мы не видим ошибки.sub do_die { die "Error"; } eval { local $@; do_die(); }; if ($@) { print "Error [$@] Occured!"; }
Потенциальная проблема #2
Если в деструкторе используется eval, то скорее всего мы не перехватим исключение. Пример:package Object; sub new { my $class = shift; my $self = {}; bless $self, $class; } sub DESTROY { eval { # some clean code } } package main; eval { my $obj = Object->new(); die "Error"; }; if ($@) { print "Error [$@] Occured!"; }Деструктор с eval-ом может быть в ком-то модуле с CPANа и Вы просто не будете знать про это.
Потенциальная проблема #3
$@ может содержать объект, которые в булевом контексте вернет ложь.Решение
В связи со всем вышесказанным, рекомендую использовать модуль Try::Tiny либо TryCatch. Они позволят Вам избежать описанных проблем в будущем и предоставят удобные и понятные синтаксический конструкции(try{}catch{} finally{}).
Я использую Try::Tiny, он мне нравится своей минималистичностью и отсутствием внешних зависимостей.
Вот пример кода с Try::Tiny. Красиво и надежно :).
# handle errors with a catch handler try { die "foo"; } catch { warn "caught error: $_"; # not $@ }; # just silence errors try { die "foo"; };
Более доходчиво про это все написано в "perldoc Try::Tiny".
1 коммент.:
TryCatch как-то проблемно устанавливается в последнее время (не проходит часть тестов под windows), потому тоже пользуюсь Try::Tiny, что и остальным желаю.
Отправить комментарий
Не забудьте добавить себя в постоянные читатели и включить уведомления о новых комментариях, либо воспользуйтесь RSS каналом ;)