From: Yuval Kogman Date: Tue, 1 Sep 2009 04:08:36 +0000 (+0300) Subject: minor doc and code fixes X-Git-Tag: Try-Tiny-0.02~6 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=1f7c5af69984bda216de12bb32c85cdae32647fc;p=p5sagit%2FTry-Tiny.git minor doc and code fixes --- diff --git a/lib/Try/Tiny.pm b/lib/Try/Tiny.pm index 7c99a6b..9421de4 100644 --- a/lib/Try/Tiny.pm +++ b/lib/Try/Tiny.pm @@ -109,18 +109,16 @@ Try::Tiny - minimal try/catch with proper localization of $@ =head1 DESCRIPTION This module provides bare bones C/C statements that are designed to -minimize common mistakes done with eval blocks (for instance assuming that -C<$@> is set to a true value on error, or clobbering previous values of C<$@>), -and NOTHING else. +minimize common mistakes with eval blocks, and NOTHING else. This is unlike L which provides a nice syntax and avoids adding another call stack layer, and supports calling C from the try block to return from the parent subroutine. These extra features come at a cost of a few dependencies, namely L and L which are -occasionally problematic, and the additional catch filtering using L -type constraints may not be desirable either. +occasionally problematic, and the additional catch filtering uses L +type constraints which may not be desirable either. -The main focus of this module is to provide reliable but simple error handling +The main focus of this module is to provide simple and reliable error handling for those having a hard time installing L, but who still want to write correct C blocks without 5 lines of boilerplate each time. @@ -130,28 +128,32 @@ of error values (simple strings, references, objects, overloaded objects, etc). =head1 EXPORTS -All are exported by default using L. +All functions are exported by default using L. In the future L may be used to allow the keywords to be renamed, but this technically does not satisfy Adam Kennedy's definition of "Tiny". =over 4 -=item try &;$ +=item try (&;$) -Takes one mandatory and one optional catch subroutine. +Takes one mandatory try subroutine and one optional catch subroutine. The mandatory subroutine is evaluated in the context of an C block. -If no error occurred the value from the first block is returned. +If no error occurred the value from the first block is returned, preserving +list/scalar context. If there was an error and the second subroutine was given it will be invoked with the error in C<$_> (localized) and as that block's first and only argument. -Note that the error may be false +Note that the error may be false, but if that happens the C block will +still be invoked.. -=item catch & +=item catch (&) + +Intended to be used in the second argument position of C. Just returns the subroutine it was given. @@ -161,8 +163,6 @@ is the same as sub { ... } -Intended to be used in the second argument position of C. - =back =head1 BACKGROUND @@ -174,7 +174,11 @@ There are a number of issues with C. When you run an eval block and it succeeds, C<$@> will be cleared, potentially clobbering an error that is currently being caught. -C<$@> must be properly localized before invoking C in order to avoid this issue. +This causes action at a distance, clearing previous errors your caller may have +not yet handled. + +C<$@> must be properly localized before invoking C in order to avoid this +issue. =head2 Localizing $@ silently masks errors @@ -186,7 +190,7 @@ Inside an eval block C behaves sort of like: } This means that if you were polite and localized C<$@> you can't die in that -scope while propagating your error. +scope, or your error will be discarded (printing "Something's wrong" instead). The workaround is very ugly: @@ -207,9 +211,10 @@ This code is wrong: ... } -because due to the previous caveats it may have been unset. $@ could also an -overloaded error object that evaluates to false, but that's asking for trouble -anyway. +because due to the previous caveats it may have been unset. + +C<$@> could also an overloaded error object that evaluates to false, but that's +asking for trouble anyway. The classic failure mode is: @@ -227,16 +232,16 @@ The classic failure mode is: } -In this case since C is not localizing C<$@> but using eval it -will set C<$@> to C<"">. +In this case since C is not localizing C<$@> but still uses +C it will set C<$@> to C<"">. -The destructor is only fired after C sets C<$@> to +The destructor is called when the stack is unwound, after C sets C<$@> to C<"foo at Foo.pm line 42\n">, so by the time C is evaluated it has -become false. +been cleared by C in the destructor. -The workaround for this is even uglier. Even though we can't save the value of -C<$@> from code that doesn't localize it but uses C in destructors, we -can at least be sure there was an error: +The workaround for this is even uglier than the previous ones. Even though we +can't save the value of C<$@> from code that doesn't localize, we can at least +be sure the eval was aborted due to an error: my $failed = not eval { ... @@ -244,15 +249,15 @@ can at least be sure there was an error: return 1; }; -This is because an C that caught a C will always behave like -C with no arguments. +This is because an C that caught a C will always return a false +value. =head1 SHINY SYNTAX -Using Perl 5.10 you can enable the C/C construct. The C -block is invoked in a topicalizer context (like a C block). +Using Perl 5.10 you can use L. -Note that you can't return a useful value from C using the C +The C block is invoked in a topicalizer context (like a C block), +but note that you can't return a useful value from C using the C blocks without an explicit C. This is somewhat similar to Perl 6's C blocks. You can use it to @@ -261,7 +266,7 @@ concisely match errors: try { require Foo; } catch { - when (qr/^Can't locate .*?\.pm in \@INC/) { } # ignore + when (/^Can't locate .*?\.pm in \@INC/) { } # ignore default { die $_ } } @@ -271,14 +276,15 @@ concisely match errors: =item * -Introduces another caller stack frame. L is not used. L -will report this when using full stack traces. This is considered a feature. +C introduces another caller stack frame. L is not used. L +will report this when using full stack traces. This lack of magic is considered +a feature. =item * The value of C<$_> in the C block is not guaranteed to be preserved, there is no safe way to ensure this if C is used unhygenically in -destructors. It is guaranteed that C will be called, though. +destructors. It's only guaranteeed that the C will be called. =back diff --git a/t/basic.t b/t/basic.t index e438d48..bbef5d6 100644 --- a/t/basic.t +++ b/t/basic.t @@ -39,10 +39,6 @@ sub throws_ok (&$$) { } -sub Evil::DESTROY { - eval { "oh noes" }; -} - lives_ok { try { die "foo"; @@ -79,12 +75,18 @@ is_deeply( [ try {qw(foo bar gorch)} ], [qw(foo bar gorch)], "list context" ); +sub Evil::DESTROY { + eval { "oh noes" }; +} + +sub Evil::new { bless { }, $_[0] } + { local $@ = "magic"; local $_ = "other magic"; try { - my $object = bless { }, "Evil"; + my $object = Evil->new; die "foo"; } catch { pass("catch invoked");