Нельзя создать его с new
и вернуть его. Они имеют метод throw
, который автоматически выполняет функцию конструктора и die
.
use strict;
use warnings;
use Exception::Class qw(InputException HTTPException);
use Try::Tiny;
sub get_html {
my ($url) = @_;
# input validation
InputException->throw(error => 'no URL') unless $url;
my $res = $ua->get($url);
if ($res->is_success) {
# do more stuff with $res;
} else {
HTTPException->throw(error => 'request failed');
}
}
# ... later
my $url;
try {
get_html($url);
} catch {
# handle the error which is in $_
if ($_->isa('InputException')) {
print "You need to supply a URL";
} elsif ($_->isa('HTTPException')) {
print "Could not fetch the HTML because the HTTP request failed.\n";
print "But I am not telling you why.";
}
}
Вы можете пойти и catch
(использовать Try::Tiny для этого), или просто обернуть его в Eval. Но в основном эти исключения являются простыми объектами. Они предназначены как возвращаемое значение die
и их выбрасывают, поэтому нет необходимости возвращать их в любом месте.
После того, как программа замирает, все области действия стека вызовов выходят принудительно, пока вы не окажетесь в блоке eval
(что и делает catch
). Там вы можете справиться с ошибкой. И поскольку эта ошибка является объектом, вы можете с ней притворяться.
+--------------------------------------------------------------------+
| sub { |
| +----------------------------------------------------------------+ |
| | if() { | |
| | +------------------------------------------------------------+ | |
| | | foo:: sub { | | |
| | | +--------------------------------------------------------+ | | |
| | | | catch { | | | |
| | | | +----------------------------------------------------+ | | | |
| | | | | doo_stuff:: sub { | | | | |
| | | | | +------------------------------------------------+ | | | | |
| | | | | | | | | | | |
| | | | | | MyException->throw ==> die $obj +---------------------------------+
| | | | | | do_more_stuff(); # never executed | | | | | | |
| | | | | | | | | | | | |
| | | | | +------------------------------------------------+ | | | | | |
| | | | +----------------------------------------------------+ | | | | |
| | | | | | | | |
| | | | handle_exception_in_catch($_) <---------------------------------+
| | | | # (in Try::Tiny the exception ends up in $_) | | | |
| | | | | | | |
| | | +--------------------------------------------------------+ | | |
| | +------------------------------------------------------------+ | |
| +----------------------------------------------------------------+ |
+--------------------------------------------------------------------+
Смотрите также Exception::Class документы.
Если смешать исключения и регулярные die
или Carpcroak
звонков, вам придется делать много проверки, если материал благословляется перед использованием ->isa
. Safe::Isa пригодится здесь.
use strict;
use warnings;
use Exception::Class qw(InputException HTTPException);
use Try::Tiny;
use Safe::Isa;
sub get_html {
my ($url) = @_;
# input validation
InputException->throw(error => 'no URL') unless $url;
my $res = $ua->get($url);
if ($res->is_success) {
# do more stuff with $res;
die "There is no answer in this HTML" if $res->decoded_content !~ m/42/;
} else {
HTTPException->throw(error => 'request failed');
}
}
С помощью этого кода, то $_->isa('...')
взорвется, потому что в случае die
вызова $_
не является объект, и вы не можете вызвать метод isa
на качестве неблагословленных ссылок (или не ссылки).Safe :: Isa предоставляет $_isa
, который проверяет это первым и в противном случае просто возвращает false
.
my $url;
try {
get_html($url);
} catch {
# handle the error which is in $_
if ($_->$_isa('InputException')) {
print "You need to supply a URL";
} elsif ($_->$_isa('HTTPException')) {
print "Could not fetch the HTML because the HTTP request failed.\n";
print "But I am not telling you why.";
}
}
Для получения дополнительной информации о том, как это работает, см mst's talk You did what?
Почему вы ожидаете, что они лжецы? Вы путаете их с возвратом ложных за неудачу? – Schwern
@Schwern Я добавил код на вопрос. Я хочу, чтобы у меня была возможность остановить функцию и сказать, что кто-то поступил неправильно, не убив всю программу. по какой-то причине я, хотя и объект исключения оценил бы false – user2348668