mention Throwable in SEE ALSO
[p5sagit/Try-Tiny.git] / lib / Try / Tiny.pm
CommitLineData
3176feef 1package Try::Tiny;
2
3use strict;
ae53da51 4#use warnings;
3176feef 5
ae53da51 6use vars qw(@EXPORT @EXPORT_OK $VERSION @ISA);
7
8BEGIN {
9 require Exporter;
10 @ISA = qw(Exporter);
11}
3176feef 12
13$VERSION = "0.01";
14
15$VERSION = eval $VERSION;
16
17@EXPORT = @EXPORT_OK = qw(try catch);
18
19sub try (&;$) {
20 my ( $try, $catch ) = @_;
21
22 # we need to save this here, the eval block will be in scalar context due
23 # to $failed
24 my $wantarray = wantarray;
25
26 my ( @ret, $error, $failed );
27
28 # FIXME consider using local $SIG{__DIE__} to accumilate all errors. It's
29 # not perfect, but we could provide a list of additional errors for
30 # $catch->();
31
32 {
33 # localize $@ to prevent clobbering of previous value by a successful
34 # eval.
35 local $@;
36
37 # failed will be true if the eval dies, because 1 will not be returned
38 # from the eval body
39 $failed = not eval {
40
41 # evaluate the try block in the correct context
42 if ( $wantarray ) {
43 @ret = $try->();
44 } elsif ( defined $wantarray ) {
45 $ret[0] = $try->();
46 } else {
47 $try->();
48 };
49
50 return 1; # properly set $fail to false
51 };
52
53 # copy $@ to $error, when we leave this scope local $@ will revert $@
54 # back to its previous value
55 $error = $@;
56 }
57
58 # at this point $failed contains a true value if the eval died even if some
59 # destructor overwrite $@ as the eval was unwinding.
60 if ( $failed ) {
61 # if we got an error, invoke the catch block.
62 if ( $catch ) {
63 # This works like given($error), but is backwards compatible and
64 # sets $_ in the dynamic scope for the body of C<$catch>
65 for ($error) {
66 return $catch->($error);
67 }
44599111 68
69 # in case when() was used without an explicit return, the C<for>
70 # loop will be aborted and there's no useful return value
3176feef 71 }
44599111 72
73 return;
3176feef 74 } else {
75 # no failure, $@ is back to what it was, everything is fine
76 return $wantarray ? @ret : $ret[0];
77 }
78}
79
80sub catch (&) {
81 return $_[0];
82}
83
84
85__PACKAGE__
86
87__END__
88
89=pod
90
91=head1 NAME
92
93Try::Tiny - minimal try/catch with proper localization of $@
94
95=head1 SYNOPSIS
96
97 # handle errors with a catch handler
98 try {
99 die "foo";
100 } catch {
101 warn "caught error: $_";
102 };
103
104 # just silence errors
105 try {
106 die "foo";
107 };
108
109=head1 DESCRIPTION
110
111This module provides bare bones C<try>/C<catch> statements that are designed to
112minimize common mistakes done with eval blocks (for instance assuming that
113C<$@> is set to a true value on error, or clobbering previous values of C<$@>),
114and NOTHING else.
115
116This is unlike L<TryCatch> which provides a nice syntax and avoids adding
117another call stack layer, and supports calling C<return> from the try block to
118return from the parent subroutine. These extra features come at a cost of a few
119dependencies, namely L<Devel::Declare> and L<Scope::Upper> which are
120occasionally problematic, and the additional catch filtering using L<Moose>
121type constraints may not be desirable either.
122
123The main focus of this module is to provide reliable but simple error handling
124for those having a hard time installing L<TryCatch>, but who still want to
125write correct C<eval> blocks without 5 lines of boilerplate each time.
126
127It's designed to work as correctly as possible in light of the various
128pathological edge cases (see L<BACKGROUND>) and to be compatible with any style
129of error values (simple strings, references, objects, overloaded objects, etc).
130
131=head1 EXPORTS
132
133All are exported by default using L<Exporter>.
134
a717a876 135In the future L<Sub::Exporter> may be used to allow the keywords to be renamed,
3176feef 136but this technically does not satisfy Adam Kennedy's definition of "Tiny".
137
138=over 4
139
140=item try &;$
141
142Takes one mandatory and one optional catch subroutine.
143
144The mandatory subroutine is evaluated in the context of an C<eval> block.
145
a717a876 146If no error occurred the value from the first block is returned.
3176feef 147
148If there was an error and the second subroutine was given it will be invoked
149with the error in C<$_> (localized) and as that block's first and only
150argument.
151
152Note that the error may be false
153
154=item catch &
155
a717a876 156Just returns the subroutine it was given.
3176feef 157
158 catch { ... }
159
160is the same as
161
162 sub { ... }
163
164Intended to be used in the second argument position of C<try>.
165
166=back
167
168=head1 BACKGROUND
169
170There are a number of issues with C<eval>.
171
172=head2 Clobbering $@
173
174When you run an eval block and it succeeds, C<$@> will be cleared, potentially
a717a876 175clobbering an error that is currently being caught.
3176feef 176
177C<$@> must be properly localized before invoking C<eval> in order to avoid this issue.
178
179=head2 Localizing $@ silently masks errors
180
181Inside an eval block C<die> behaves sort of like:
182
183 sub die {
184 $@_ = $_[0];
185 return_undef_from_eval();
186 }
187
188This means that if you were polite and localized C<$@> you can't die in that
189scope while propagating your error.
190
191The workaround is very ugly:
192
193 my $error = do {
194 local $@;
195 eval { ... };
196 $@;
197 };
198
199 ...
200 die $error;
201
202=head2 $@ might not be a true value
203
204This code is wrong:
205
206 if ( $@ ) {
207 ...
208 }
209
210because due to the previous caveats it may have been unset. $@ could also an
211overloaded error object that evaluates to false, but that's asking for trouble
212anyway.
213
214The classic failure mode is:
215
216 sub Object::DESTROY {
217 eval { ... }
218 }
219
220 eval {
221 my $obj = Object->new;
222
223 die "foo";
224 };
225
226 if ( $@ ) {
227
228 }
229
230In this case since C<Object::DESTROY> is not localizing C<$@> but using eval it
231will set C<$@> to C<"">.
232
233The destructor is only fired after C<die> sets C<$@> to
234C<"foo at Foo.pm line 42\n">, so by the time C<if ( $@ )> is evaluated it has
235become false.
236
237The workaround for this is even uglier. Even though we can't save the value of
238C<$@> from code that doesn't localize it but uses C<eval> in destructors, we
239can at least be sure there was an error:
240
241 my $failed = not eval {
242 ...
243
244 return 1;
245 };
246
247This is because an C<eval> that caught a C<die> will always behave like
248C<return> with no arguments.
249
f9b91e2c 250=head1 SHINY SYNTAX
3176feef 251
252Using Perl 5.10 you can enable the C<given>/C<when> construct. The C<catch>
253block is invoked in a topicalizer context (like a C<given> block).
254
255Note that you can't return a useful value from C<catch> using the C<when>
27293e40 256blocks without an explicit C<return>.
3176feef 257
258This is somewhat similar to Perl 6's C<CATCH> blocks. You can use it to
259concisely match errors:
260
261 try {
262 require Foo;
263 } catch {
264 when (qr/^Can't locate .*?\.pm in \@INC/) { } # ignore
265 default { die $_ }
266 }
267
268=head1 CAVEATS
269
270=over 4
271
272=item *
273
274Introduces another caller stack frame. L<Sub::Uplevel> is not used. L<Carp>
275will report this when using full stack traces. This is considered a feature.
276
277=item *
278
279The value of C<$_> in the C<catch> block is not guaranteed to be preserved,
280there is no safe way to ensure this if C<eval> is used unhygenically in
281destructors. It is guaranteed that C<catch> will be called, though.
282
283=back
284
285=head1 SEE ALSO
286
287=over 4
288
289=item L<TryCatch>
290
291Much more feature complete, more convenient semantics, but at the cost of
292implementation complexity.
293
f8227e43 294=item L<Throwable>
295
296A lightweight role for rolling your own exception classes.
297
3176feef 298=item L<Error>
299
300Exception object implementation with a C<try> statement. Does not localize
301C<$@>.
302
303=item L<Exception::Class::TryCatch>
304
305Provides a C<catch> statement, but properly calling C<eval> is your
306responsibility.
307
308The C<try> keyword pushes C<$@> onto an error stack, avoiding some of the
309issues with C<$@> but you still need to localize to prevent clobbering.
310
311=back
312
313=head1 VERSION CONTROL
314
315L<http://github.com/nothingmuch/try-tiny/>
316
317=head1 AUTHOR
318
319Yuval Kogman E<lt>nothingmuch@woobling.orgE<gt>
320
321=head1 COPYRIGHT
322
c4e1eb12 323 Copyright (c) 2009 Yuval Kogman. All rights reserved.
3176feef 324 This program is free software; you can redistribute
c4e1eb12 325 it and/or modify it under the terms of the MIT license.
3176feef 326
327=cut
328