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