Restore list context for catch and fix a bug in finally with no catch
Yuval Kogman [Fri, 22 Jan 2010 20:04:47 +0000 (21:04 +0100)]
lib/Try/Tiny.pm
t/basic.t
t/finally.t

index 65c8867..b0bdcf1 100644 (file)
@@ -84,6 +84,9 @@ sub try (&;@) {
                $error = $@;
        }
 
+       # set up a scope guard to invoke the finally block at the end
+       my $guard = $finally && bless \$finally, "Try::Tiny::ScopeGuard";
+
        # at this point $failed contains a true value if the eval died, even if some
        # destructor overwrote $@ as the eval was unwinding.
        if ( $failed ) {
@@ -92,13 +95,7 @@ sub try (&;@) {
                        # This works like given($error), but is backwards compatible and
                        # sets $_ in the dynamic scope for the body of C<$catch>
                        for ($error) {
-                               my $catch_return = $catch->($error);
-
-                               # Finally blocks run after all other blocks so it is executed here
-                               $finally->() if ( $finally );
-
-                               #And return whatever catch returned
-                               return $catch_return;
+                               return $catch->($error);
                        }
 
                        # in case when() was used without an explicit return, the C<for>
@@ -107,9 +104,6 @@ sub try (&;@) {
 
                return;
        } else {
-               # Execute finally block once we decided we worked
-               $finally->() if ( $finally );
-
                # no failure, $@ is back to what it was, everything is fine
                return $wantarray ? @ret : $ret[0];
        }
@@ -133,6 +127,11 @@ sub finally (&;@) {
        );
 }
 
+sub Try::Tiny::ScopeGuard::DESTROY {
+       my $self = shift;
+       $$self->();
+}
+
 __PACKAGE__
 
 __END__
index ba71ed3..022c604 100644 (file)
--- a/t/basic.t
+++ b/t/basic.t
@@ -3,7 +3,7 @@
 use strict;
 #use warnings;
 
-use Test::More tests => 24;
+use Test::More tests => 26;
 
 BEGIN { use_ok 'Try::Tiny' };
 
@@ -72,8 +72,12 @@ throws_ok {
        is( $@, "magic", '$@ untouched' );
 }
 
-is( scalar(try { "foo", "bar", "gorch" }), "gorch", "scalar context" );
-is_deeply( [ try {qw(foo bar gorch)} ], [qw(foo bar gorch)], "list context" );
+is( scalar(try { "foo", "bar", "gorch" }), "gorch", "scalar context try" );
+is_deeply( [ try {qw(foo bar gorch)} ], [qw(foo bar gorch)], "list context try" );
+
+is( scalar(try { die } catch { "foo", "bar", "gorch" }), "gorch", "scalar context catch" );
+is_deeply( [ try { die } catch {qw(foo bar gorch)} ], [qw(foo bar gorch)], "list context catch" );
+
 
 {
        my ($sub) = catch { my $a = $_; };
index d8bd0d4..1310633 100644 (file)
@@ -3,7 +3,7 @@
 use strict;
 #use warnings;
 
-use Test::More tests => 7;
+use Test::More tests => 8;
 
 BEGIN { use_ok 'Try::Tiny' };