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