X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FTry%2FTiny.pm;h=33316602a7e456eff27377539276c20e66baa1a2;hb=5f5e92c0e36725a449c010c445eba40589ac8bf6;hp=9d46a7629ef1eb40ac5ad59c085d89d73db1166f;hpb=2b0d579d80e5316f00183930df181ea36f80e517;p=p5sagit%2FTry-Tiny.git diff --git a/lib/Try/Tiny.pm b/lib/Try/Tiny.pm index 9d46a76..3331660 100644 --- a/lib/Try/Tiny.pm +++ b/lib/Try/Tiny.pm @@ -28,16 +28,19 @@ sub try (&;@) { # find labeled blocks in the argument list. # catch and finally tag the blocks by blessing a scalar reference to them. foreach my $code_ref (@code_refs) { - next unless $code_ref; - my $ref = ref($code_ref); - - if ( $ref eq 'Try::Tiny::Catch' ) { + if ( ref($code_ref) eq 'Try::Tiny::Catch' ) { + croak 'A try() may not be followed by multiple catch() blocks' + if $catch; $catch = ${$code_ref}; - } elsif ( $ref eq 'Try::Tiny::Finally' ) { + } elsif ( ref($code_ref) eq 'Try::Tiny::Finally' ) { push @finally, ${$code_ref}; } else { - confess("Unknown code ref type given '${ref}'. Check your usage & try again"); + croak( + 'try() encountered an unexpected argument (' + . ( defined $code_ref ? $code_ref : 'undef' ) + . ') - perhaps a missing semi-colon before or' + ); } } @@ -101,6 +104,8 @@ sub try (&;@) { sub catch (&;@) { my ( $block, @rest ) = @_; + croak 'Useless bare catch()' unless defined wantarray; + return ( bless(\$block, 'Try::Tiny::Catch'), @rest, @@ -110,6 +115,8 @@ sub catch (&;@) { sub finally (&;@) { my ( $block, @rest ) = @_; + croak 'Useless bare finally()' unless defined wantarray; + return ( bless(\$block, 'Try::Tiny::Finally'), @rest, @@ -120,15 +127,30 @@ sub finally (&;@) { package # hide from PAUSE Try::Tiny::ScopeGuard; + use constant UNSTABLE_DOLLARAT => ($] < '5.013002') ? 1 : 0; + sub _new { shift; bless [ @_ ]; } sub DESTROY { - my @guts = @{ shift() }; - my $code = shift @guts; - $code->(@guts); + my ($code, @args) = @{ $_[0] }; + + local $@ if UNSTABLE_DOLLARAT; + eval { + $code->(@args); + 1; + } or do { + warn + "Execution of finally() block $code resulted in an exception, which " + . '*CAN NOT BE PROPAGATED* due to fundamental limitations of Perl. ' + . 'Your program will continue as if this event never took place. ' + . "Original exception text follows:\n\n" + . (defined $@ ? $@ : '$@ left undefined...') + . "\n" + ; + } } } @@ -235,7 +257,7 @@ still be invoked. Once all execution is finished then the C block, if given, will execute. -=item catch (&;$) +=item catch (&;@) Intended to be used in the second argument position of C. @@ -255,7 +277,7 @@ L), you'll need to do: local $@ = $_; -=item finally (&;$) +=item finally (&;@) try { ... } catch { ... } @@ -299,6 +321,11 @@ B block>. C blocks are not trappable and are unable +to influence the execution of your program>. This is due to limitation of +C-based scope guards, which C is implemented on top of. This +may change in a future version of Try::Tiny. + In the same way C blesses the code reference this subroutine does the same except it bless them as C. @@ -574,11 +601,11 @@ issues with C<$@>, but you still need to localize to prevent clobbering. I gave a lightning talk about this module, you can see the slides (Firefox only): -L +L Or read the source: -L +L =head1 VERSION CONTROL