Одним из возможных вариантов мне видится:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#!/usr/bin/perl use strict; use warnings; use MyExceptions; use MyTry; try { MyExceptions::SomeError2->throw(); } catch {MyExceptions::SomeError1->test || MyExceptions::SomeError2->test} by { print "Catched\n"; print $_->description; } catch {MyExceptions::SomeError0->n} by { print "Catched exception 0\n"; }; #<-- semicolon must be here |
Опишем классы исключений:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
package MyExceptions; use strict; use warnings; sub test { my $class = shift; return $_->isa( $class ); } sub throw { my $class = shift; die bless {}, $class; } package MyExceptions::SomeError0; use parent 'MyExceptions'; sub description {"Some text 0"}; package MyExceptions::SomeError1; use parent 'MyExceptions'; sub description {"Some text 1"}; package MyExceptions::SomeError2; use parent 'MyExceptions'; sub description {"Some text 2"}; package MyExceptions::SomeError3; use parent 'MyExceptions'; sub description {"Some text 3"}; 1; |
Опишем подобие try/catch
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
package MyTry; use vars qw(@EXPORT @EXPORT_OK $VERSION @ISA); BEGIN { require Exporter; @ISA = qw(Exporter); } $VERSION = "0.0.0.1"; @EXPORT = @EXPORT_OK = qw(try catch by); sub try(&;@){ my ($code, $ref) = @_; eval{ $code->(); }; if(defined $@){ my $e = $@; my $cathed = 0; my $deep = 10; #maximum catch/by blocks count while(defined $ref && !$cathed && $deep){ if(ref $ref eq 'My::Catch' && defined $ref->{following} && ref $ref->{following} eq 'My::By'){ $_ = $e; eval{ if($ref->{code}->()){ $cathed = 1; $ref->{following}->{code}->(); } }; $ref = $ref->{following}->{following}; }else{ die "Something is wrong!!!"; } $deep--; } die $e unless $cathed; } } sub catch(&;@){ my ($code, $ref) = @_; return bless {code => $code, following => $ref}, 'My::Catch'; } sub by(&;@){ my ($code, $ref) = @_; return bless {code => $code, following => $ref}, 'My::By'; } 1; |
Другие примеры:
1 2 3 4 5 6 7 8 9 |
try { try { MyExceptions::SomeError0->throw(); } catch { MyExceptions::SomeError0->test } by { print "In another try\n"; }; } catch { MyExceptions::SomeError2->test } by { print "In try\n"; }; |
выводит:
1 |
In another try |
1 2 3 4 5 6 7 8 9 |
try { try { MyExceptions::SomeError2->throw(); } catch { MyExceptions::SomeError0->test } by { print "In another try\n"; }; } catch { MyExceptions::SomeError2->test } by { print "In try\n"; }; |
выводит:
1 |
In try |