File | /usr/local/share/perl/5.10.0/Try/Tiny.pm |
Statements Executed | 6702 |
Total Time | 0.00810619999999996 seconds |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
304 | 3 | 3 | 5.97ms | 114ms | try | Try::Tiny::
304 | 3 | 3 | 2.06ms | 2.06ms | catch | Try::Tiny::
0 | 0 | 0 | 0s | 0s | BEGIN | Try::Tiny::
0 | 0 | 0 | 0s | 0s | DESTROY | Try::Tiny::ScopeGuard::
0 | 0 | 0 | 0s | 0s | _new | Try::Tiny::ScopeGuard::
0 | 0 | 0 | 0s | 0s | finally | Try::Tiny::
Line | Stmts. | Exclusive Time | Avg. | Code |
---|---|---|---|---|
1 | package Try::Tiny; | |||
2 | ||||
3 | 3 | 30µs | 10µs | use strict; # spent 9µs making 1 call to strict::import |
4 | #use warnings; | |||
5 | ||||
6 | 3 | 44µs | 15µs | use vars qw(@EXPORT @EXPORT_OK $VERSION @ISA); # spent 70µs making 1 call to vars::import |
7 | ||||
8 | BEGIN { | |||
9 | 2 | 12µs | 6µs | require Exporter; |
10 | @ISA = qw(Exporter); | |||
11 | 1 | 131µs | 131µs | } |
12 | ||||
13 | 1 | 800ns | 800ns | $VERSION = "0.07"; |
14 | ||||
15 | 1 | 20µs | 20µs | $VERSION = eval $VERSION; |
16 | ||||
17 | 1 | 3µs | 3µs | @EXPORT = @EXPORT_OK = qw(try catch finally); |
18 | ||||
19 | 1 | 4µs | 4µs | $Carp::Internal{+__PACKAGE__}++; |
20 | ||||
21 | # Need to prototype as @ not $$ because of the way Perl evaluates the prototype. | |||
22 | # Keeping it at $$ means you only ever get 1 sub because we need to eval in a list | |||
23 | # context & not a scalar one | |||
24 | ||||
25 | # spent 114ms (5.97+108) within Try::Tiny::try which was called 304 times, avg 375µs/call:
# 177 times (3.58ms+24.8ms) by Class::MOP::Attribute::_process_accessors or Class::MOP::Attribute::__ANON__[/usr/local/lib/perl/5.10.0/Class/MOP/Attribute.pm:345] at line 345 of /usr/local/lib/perl/5.10.0/Class/MOP/Attribute.pm, avg 160µs/call
# 123 times (2.29ms+58.0ms) by Class::MOP::Class::_post_add_attribute or Class::MOP::Class::__ANON__[/usr/local/lib/perl/5.10.0/Class/MOP/Class.pm:772] at line 772 of /usr/local/lib/perl/5.10.0/Class/MOP/Class.pm, avg 490µs/call
# 4 times (105µs+25.4ms) by Class::MOP::load_first_existing_class or Class::MOP::__ANON__[/usr/local/lib/perl/5.10.0/Class/MOP.pm:124] at line 124 of /usr/local/lib/perl/5.10.0/Class/MOP.pm, avg 6.36ms/call | |||
26 | 2736 | 2.00ms | 731ns | my ( $try, @code_refs ) = @_; |
27 | ||||
28 | # we need to save this here, the eval block will be in scalar context due | |||
29 | # to $failed | |||
30 | my $wantarray = wantarray; | |||
31 | ||||
32 | my ( $catch, @finally ); | |||
33 | ||||
34 | # find labeled blocks in the argument list. | |||
35 | # catch and finally tag the blocks by blessing a scalar reference to them. | |||
36 | foreach my $code_ref (@code_refs) { | |||
37 | 912 | 969µs | 1µs | next unless $code_ref; |
38 | ||||
39 | my $ref = ref($code_ref); | |||
40 | ||||
41 | if ( $ref eq 'Try::Tiny::Catch' ) { | |||
42 | $catch = ${$code_ref}; | |||
43 | } elsif ( $ref eq 'Try::Tiny::Finally' ) { | |||
44 | push @finally, ${$code_ref}; | |||
45 | } else { | |||
46 | 3 | 402µs | 134µs | use Carp; # spent 51µs making 1 call to Exporter::import |
47 | confess("Unknown code ref type given '${ref}'. Check your usage & try again"); | |||
48 | } | |||
49 | } | |||
50 | ||||
51 | # save the value of $@ so we can set $@ back to it in the beginning of the eval | |||
52 | my $prev_error = $@; | |||
53 | ||||
54 | my ( @ret, $error, $failed ); | |||
55 | ||||
56 | # FIXME consider using local $SIG{__DIE__} to accumulate all errors. It's | |||
57 | # not perfect, but we could provide a list of additional errors for | |||
58 | # $catch->(); | |||
59 | ||||
60 | { | |||
61 | # localize $@ to prevent clobbering of previous value by a successful | |||
62 | # eval. | |||
63 | 912 | 808µs | 886ns | local $@; |
64 | ||||
65 | # failed will be true if the eval dies, because 1 will not be returned | |||
66 | # from the eval body | |||
67 | 912 | 592µs | 650ns | $failed = not eval { |
68 | $@ = $prev_error; | |||
69 | ||||
70 | # evaluate the try block in the correct context | |||
71 | 300 | 1.19ms | 4µs | if ( $wantarray ) { # spent 25.4ms making 4 calls to Class::MOP::__ANON__[/usr/local/lib/perl/5.10.0/Class/MOP.pm:117], avg 6.34ms/call |
72 | @ret = $try->(); | |||
73 | } elsif ( defined $wantarray ) { | |||
74 | $ret[0] = $try->(); | |||
75 | } else { | |||
76 | $try->(); # spent 59.5ms making 123 calls to Class::MOP::Class::__ANON__[/usr/local/lib/perl/5.10.0/Class/MOP/Class.pm:768], avg 484µs/call
# spent 48.8ms making 177 calls to Class::MOP::Attribute::__ANON__[/usr/local/lib/perl/5.10.0/Class/MOP/Attribute.pm:342], avg 276µs/call | |||
77 | }; | |||
78 | ||||
79 | return 1; # properly set $fail to false | |||
80 | }; | |||
81 | ||||
82 | # copy $@ to $error; when we leave this scope, local $@ will revert $@ | |||
83 | # back to its previous value | |||
84 | $error = $@; | |||
85 | } | |||
86 | ||||
87 | # set up a scope guard to invoke the finally block at the end | |||
88 | my @guards = | |||
89 | map { Try::Tiny::ScopeGuard->_new($_, $failed ? $error : ()) } | |||
90 | @finally; | |||
91 | ||||
92 | # at this point $failed contains a true value if the eval died, even if some | |||
93 | # destructor overwrote $@ as the eval was unwinding. | |||
94 | 304 | 641µs | 2µs | if ( $failed ) { |
95 | # if we got an error, invoke the catch block. | |||
96 | if ( $catch ) { | |||
97 | # This works like given($error), but is backwards compatible and | |||
98 | # sets $_ in the dynamic scope for the body of C<$catch> | |||
99 | for ($error) { | |||
100 | return $catch->($error); | |||
101 | } | |||
102 | ||||
103 | # in case when() was used without an explicit return, the C<for> | |||
104 | # loop will be aborted and there's no useful return value | |||
105 | } | |||
106 | ||||
107 | return; | |||
108 | } else { | |||
109 | # no failure, $@ is back to what it was, everything is fine | |||
110 | return $wantarray ? @ret : $ret[0]; | |||
111 | } | |||
112 | } | |||
113 | ||||
114 | # spent 2.06ms within Try::Tiny::catch which was called 304 times, avg 7µs/call:
# 177 times (1.16ms+0s) by Class::MOP::Attribute::_process_accessors or Class::MOP::Attribute::__ANON__[/usr/local/lib/perl/5.10.0/Class/MOP/Attribute.pm:345] at line 345 of /usr/local/lib/perl/5.10.0/Class/MOP/Attribute.pm, avg 7µs/call
# 123 times (865µs+0s) by Class::MOP::Class::_post_add_attribute or Class::MOP::Class::__ANON__[/usr/local/lib/perl/5.10.0/Class/MOP/Class.pm:772] at line 772 of /usr/local/lib/perl/5.10.0/Class/MOP/Class.pm, avg 7µs/call
# 4 times (40µs+0s) by Class::MOP::load_first_existing_class or Class::MOP::__ANON__[/usr/local/lib/perl/5.10.0/Class/MOP.pm:124] at line 124 of /usr/local/lib/perl/5.10.0/Class/MOP.pm, avg 10µs/call | |||
115 | 608 | 1.25ms | 2µs | my ( $block, @rest ) = @_; |
116 | ||||
117 | return ( | |||
118 | bless(\$block, 'Try::Tiny::Catch'), | |||
119 | @rest, | |||
120 | ); | |||
121 | } | |||
122 | ||||
123 | sub finally (&;@) { | |||
124 | my ( $block, @rest ) = @_; | |||
125 | ||||
126 | return ( | |||
127 | bless(\$block, 'Try::Tiny::Finally'), | |||
128 | @rest, | |||
129 | ); | |||
130 | } | |||
131 | ||||
132 | { | |||
133 | 1 | 900ns | 900ns | package Try::Tiny::ScopeGuard; |
134 | ||||
135 | sub _new { | |||
136 | shift; | |||
137 | bless [ @_ ]; | |||
138 | } | |||
139 | ||||
140 | sub DESTROY { | |||
141 | my @guts = @{ shift() }; | |||
142 | my $code = shift @guts; | |||
143 | $code->(@guts); | |||
144 | } | |||
145 | } | |||
146 | ||||
147 | __PACKAGE__ | |||
148 | ||||
149 | 1 | 10µs | 10µs | __END__ |
150 | ||||
151 | =pod | |||
152 | ||||
153 | =head1 NAME | |||
154 | ||||
155 | Try::Tiny - minimal try/catch with proper localization of $@ | |||
156 | ||||
157 | =head1 SYNOPSIS | |||
158 | ||||
159 | # handle errors with a catch handler | |||
160 | try { | |||
161 | die "foo"; | |||
162 | } catch { | |||
163 | warn "caught error: $_"; # not $@ | |||
164 | }; | |||
165 | ||||
166 | # just silence errors | |||
167 | try { | |||
168 | die "foo"; | |||
169 | }; | |||
170 | ||||
171 | =head1 DESCRIPTION | |||
172 | ||||
173 | This module provides bare bones C<try>/C<catch>/C<finally> statements that are designed to | |||
174 | minimize common mistakes with eval blocks, and NOTHING else. | |||
175 | ||||
176 | This is unlike L<TryCatch> which provides a nice syntax and avoids adding | |||
177 | another call stack layer, and supports calling C<return> from the try block to | |||
178 | return from the parent subroutine. These extra features come at a cost of a few | |||
179 | dependencies, namely L<Devel::Declare> and L<Scope::Upper> which are | |||
180 | occasionally problematic, and the additional catch filtering uses L<Moose> | |||
181 | type constraints which may not be desirable either. | |||
182 | ||||
183 | The main focus of this module is to provide simple and reliable error handling | |||
184 | for those having a hard time installing L<TryCatch>, but who still want to | |||
185 | write correct C<eval> blocks without 5 lines of boilerplate each time. | |||
186 | ||||
187 | It's designed to work as correctly as possible in light of the various | |||
188 | pathological edge cases (see L<BACKGROUND>) and to be compatible with any style | |||
189 | of error values (simple strings, references, objects, overloaded objects, etc). | |||
190 | ||||
191 | If the try block dies, it returns the value of the last statement executed in | |||
192 | the catch block, if there is one. Otherwise, it returns C<undef> in scalar | |||
193 | context or the empty list in list context. The following two examples both | |||
194 | assign C<"bar"> to C<$x>. | |||
195 | ||||
196 | my $x = try { die "foo" } catch { "bar" }; | |||
197 | ||||
198 | my $x = eval { die "foo" } || "bar"; | |||
199 | ||||
200 | You can add finally blocks making the following true. | |||
201 | ||||
202 | my $x; | |||
203 | try { die 'foo' } finally { $x = 'bar' }; | |||
204 | try { die 'foo' } catch { warn "Got a die: $_" } finally { $x = 'bar' }; | |||
205 | ||||
206 | Finally blocks are always executed making them suitable for cleanup code | |||
207 | which cannot be handled using local. You can add as many finally blocks to a | |||
208 | given try block as you like. | |||
209 | ||||
210 | =head1 EXPORTS | |||
211 | ||||
212 | All functions are exported by default using L<Exporter>. | |||
213 | ||||
214 | If you need to rename the C<try>, C<catch> or C<finally> keyword consider using | |||
215 | L<Sub::Import> to get L<Sub::Exporter>'s flexibility. | |||
216 | ||||
217 | =over 4 | |||
218 | ||||
219 | =item try (&;@) | |||
220 | ||||
221 | Takes one mandatory try subroutine, an optional catch subroutine & finally | |||
222 | subroutine. | |||
223 | ||||
224 | The mandatory subroutine is evaluated in the context of an C<eval> block. | |||
225 | ||||
226 | If no error occurred the value from the first block is returned, preserving | |||
227 | list/scalar context. | |||
228 | ||||
229 | If there was an error and the second subroutine was given it will be invoked | |||
230 | with the error in C<$_> (localized) and as that block's first and only | |||
231 | argument. | |||
232 | ||||
233 | C<$@> does B<not> contain the error. Inside the C<catch> block it has the same | |||
234 | value it had before the C<try> block was executed. | |||
235 | ||||
236 | Note that the error may be false, but if that happens the C<catch> block will | |||
237 | still be invoked. | |||
238 | ||||
239 | Once all execution is finished then the finally block if given will execute. | |||
240 | ||||
241 | =item catch (&;$) | |||
242 | ||||
243 | Intended to be used in the second argument position of C<try>. | |||
244 | ||||
245 | Returns a reference to the subroutine it was given but blessed as | |||
246 | C<Try::Tiny::Catch> which allows try to decode correctly what to do | |||
247 | with this code reference. | |||
248 | ||||
249 | catch { ... } | |||
250 | ||||
251 | Inside the catch block the caught error is stored in C<$_>, while previous | |||
252 | value of C<$@> is still available for use. This value may or may not be | |||
253 | meaningful depending on what happened before the C<try>, but it might be a good | |||
254 | idea to preserve it in an error stack. | |||
255 | ||||
256 | For code that captures C<$@> when throwing new errors (i.e. | |||
257 | L<Class::Throwable>), you'll need to do: | |||
258 | ||||
259 | local $@ = $_; | |||
260 | ||||
261 | =item finally (&;$) | |||
262 | ||||
263 | try { ... } | |||
264 | catch { ... } | |||
265 | finally { ... }; | |||
266 | ||||
267 | Or | |||
268 | ||||
269 | try { ... } | |||
270 | finally { ... }; | |||
271 | ||||
272 | Or even | |||
273 | ||||
274 | try { ... } | |||
275 | finally { ... } | |||
276 | catch { ... }; | |||
277 | ||||
278 | Intended to be the second or third element of C<try>. Finally blocks are always | |||
279 | executed in the event of a successful C<try> or if C<catch> is run. This allows | |||
280 | you to locate cleanup code which cannot be done via C<local()> e.g. closing a file | |||
281 | handle. | |||
282 | ||||
283 | When invoked, the finally block is passed the error that was caught. If no | |||
284 | error was caught, it is passed nothing. In other words, the following code | |||
285 | does just what you would expect: | |||
286 | ||||
287 | try { | |||
288 | die_sometimes(); | |||
289 | } catch { | |||
290 | # ...code run in case of error | |||
291 | } finally { | |||
292 | if (@_) { | |||
293 | print "The try block died with: @_\n"; | |||
294 | } else { | |||
295 | print "The try block ran without error.\n"; | |||
296 | } | |||
297 | }; | |||
298 | ||||
299 | B<You must always do your own error handling in the finally block>. C<Try::Tiny> will | |||
300 | not do anything about handling possible errors coming from code located in these | |||
301 | blocks. | |||
302 | ||||
303 | In the same way C<catch()> blesses the code reference this subroutine does the same | |||
304 | except it bless them as C<Try::Tiny::Finally>. | |||
305 | ||||
306 | =back | |||
307 | ||||
308 | =head1 BACKGROUND | |||
309 | ||||
310 | There are a number of issues with C<eval>. | |||
311 | ||||
312 | =head2 Clobbering $@ | |||
313 | ||||
314 | When you run an eval block and it succeeds, C<$@> will be cleared, potentially | |||
315 | clobbering an error that is currently being caught. | |||
316 | ||||
317 | This causes action at a distance, clearing previous errors your caller may have | |||
318 | not yet handled. | |||
319 | ||||
320 | C<$@> must be properly localized before invoking C<eval> in order to avoid this | |||
321 | issue. | |||
322 | ||||
323 | More specifically, C<$@> is clobbered at the beginning of the C<eval>, which | |||
324 | also makes it impossible to capture the previous error before you die (for | |||
325 | instance when making exception objects with error stacks). | |||
326 | ||||
327 | For this reason C<try> will actually set C<$@> to its previous value (before | |||
328 | the localization) in the beginning of the C<eval> block. | |||
329 | ||||
330 | =head2 Localizing $@ silently masks errors | |||
331 | ||||
332 | Inside an eval block C<die> behaves sort of like: | |||
333 | ||||
334 | sub die { | |||
335 | $@ = $_[0]; | |||
336 | return_undef_from_eval(); | |||
337 | } | |||
338 | ||||
339 | This means that if you were polite and localized C<$@> you can't die in that | |||
340 | scope, or your error will be discarded (printing "Something's wrong" instead). | |||
341 | ||||
342 | The workaround is very ugly: | |||
343 | ||||
344 | my $error = do { | |||
345 | local $@; | |||
346 | eval { ... }; | |||
347 | $@; | |||
348 | }; | |||
349 | ||||
350 | ... | |||
351 | die $error; | |||
352 | ||||
353 | =head2 $@ might not be a true value | |||
354 | ||||
355 | This code is wrong: | |||
356 | ||||
357 | if ( $@ ) { | |||
358 | ... | |||
359 | } | |||
360 | ||||
361 | because due to the previous caveats it may have been unset. | |||
362 | ||||
363 | C<$@> could also be an overloaded error object that evaluates to false, but | |||
364 | that's asking for trouble anyway. | |||
365 | ||||
366 | The classic failure mode is: | |||
367 | ||||
368 | sub Object::DESTROY { | |||
369 | eval { ... } | |||
370 | } | |||
371 | ||||
372 | eval { | |||
373 | my $obj = Object->new; | |||
374 | ||||
375 | die "foo"; | |||
376 | }; | |||
377 | ||||
378 | if ( $@ ) { | |||
379 | ||||
380 | } | |||
381 | ||||
382 | In this case since C<Object::DESTROY> is not localizing C<$@> but still uses | |||
383 | C<eval>, it will set C<$@> to C<"">. | |||
384 | ||||
385 | The destructor is called when the stack is unwound, after C<die> sets C<$@> to | |||
386 | C<"foo at Foo.pm line 42\n">, so by the time C<if ( $@ )> is evaluated it has | |||
387 | been cleared by C<eval> in the destructor. | |||
388 | ||||
389 | The workaround for this is even uglier than the previous ones. Even though we | |||
390 | can't save the value of C<$@> from code that doesn't localize, we can at least | |||
391 | be sure the eval was aborted due to an error: | |||
392 | ||||
393 | my $failed = not eval { | |||
394 | ... | |||
395 | ||||
396 | return 1; | |||
397 | }; | |||
398 | ||||
399 | This is because an C<eval> that caught a C<die> will always return a false | |||
400 | value. | |||
401 | ||||
402 | =head1 SHINY SYNTAX | |||
403 | ||||
404 | Using Perl 5.10 you can use L<perlsyn/"Switch statements">. | |||
405 | ||||
406 | The C<catch> block is invoked in a topicalizer context (like a C<given> block), | |||
407 | but note that you can't return a useful value from C<catch> using the C<when> | |||
408 | blocks without an explicit C<return>. | |||
409 | ||||
410 | This is somewhat similar to Perl 6's C<CATCH> blocks. You can use it to | |||
411 | concisely match errors: | |||
412 | ||||
413 | try { | |||
414 | require Foo; | |||
415 | } catch { | |||
416 | when (/^Can't locate .*?\.pm in \@INC/) { } # ignore | |||
417 | default { die $_ } | |||
418 | }; | |||
419 | ||||
420 | =head1 CAVEATS | |||
421 | ||||
422 | =over 4 | |||
423 | ||||
424 | =item * | |||
425 | ||||
426 | C<@_> is not available within the C<try> block, so you need to copy your | |||
427 | arglist. In case you want to work with argument values directly via C<@_> | |||
428 | aliasing (i.e. allow C<$_[1] = "foo">), you need to pass C<@_> by reference: | |||
429 | ||||
430 | sub foo { | |||
431 | my ( $self, @args ) = @_; | |||
432 | try { $self->bar(@args) } | |||
433 | } | |||
434 | ||||
435 | or | |||
436 | ||||
437 | sub bar_in_place { | |||
438 | my $self = shift; | |||
439 | my $args = \@_; | |||
440 | try { $_ = $self->bar($_) for @$args } | |||
441 | } | |||
442 | ||||
443 | =item * | |||
444 | ||||
445 | C<return> returns from the C<try> block, not from the parent sub (note that | |||
446 | this is also how C<eval> works, but not how L<TryCatch> works): | |||
447 | ||||
448 | sub bar { | |||
449 | try { return "foo" }; | |||
450 | return "baz"; | |||
451 | } | |||
452 | ||||
453 | say bar(); # "baz" | |||
454 | ||||
455 | =item * | |||
456 | ||||
457 | C<try> introduces another caller stack frame. L<Sub::Uplevel> is not used. L<Carp> | |||
458 | will not report this when using full stack traces, though, because | |||
459 | C<%Carp::Internal> is used. This lack of magic is considered a feature. | |||
460 | ||||
461 | =item * | |||
462 | ||||
463 | The value of C<$_> in the C<catch> block is not guaranteed to be the value of | |||
464 | the exception thrown (C<$@>) in the C<try> block. There is no safe way to | |||
465 | ensure this, since C<eval> may be used unhygenically in destructors. The only | |||
466 | guarantee is that the C<catch> will be called if an exception is thrown. | |||
467 | ||||
468 | =item * | |||
469 | ||||
470 | The return value of the C<catch> block is not ignored, so if testing the result | |||
471 | of the expression for truth on success, be sure to return a false value from | |||
472 | the C<catch> block: | |||
473 | ||||
474 | my $obj = try { | |||
475 | MightFail->new; | |||
476 | } catch { | |||
477 | ... | |||
478 | ||||
479 | return; # avoid returning a true value; | |||
480 | }; | |||
481 | ||||
482 | return unless $obj; | |||
483 | ||||
484 | =item * | |||
485 | ||||
486 | C<$SIG{__DIE__}> is still in effect. | |||
487 | ||||
488 | Though it can be argued that C<$SIG{__DIE__}> should be disabled inside of | |||
489 | C<eval> blocks, since it isn't people have grown to rely on it. Therefore in | |||
490 | the interests of compatibility, C<try> does not disable C<$SIG{__DIE__}> for | |||
491 | the scope of the error throwing code. | |||
492 | ||||
493 | =item * | |||
494 | ||||
495 | Lexical C<$_> may override the one set by C<catch>. | |||
496 | ||||
497 | For example Perl 5.10's C<given> form uses a lexical C<$_>, creating some | |||
498 | confusing behavior: | |||
499 | ||||
500 | given ($foo) { | |||
501 | when (...) { | |||
502 | try { | |||
503 | ... | |||
504 | } catch { | |||
505 | warn $_; # will print $foo, not the error | |||
506 | warn $_[0]; # instead, get the error like this | |||
507 | } | |||
508 | } | |||
509 | } | |||
510 | ||||
511 | =back | |||
512 | ||||
513 | =head1 SEE ALSO | |||
514 | ||||
515 | =over 4 | |||
516 | ||||
517 | =item L<TryCatch> | |||
518 | ||||
519 | Much more feature complete, more convenient semantics, but at the cost of | |||
520 | implementation complexity. | |||
521 | ||||
522 | =item L<autodie> | |||
523 | ||||
524 | Automatic error throwing for builtin functions and more. Also designed to | |||
525 | work well with C<given>/C<when>. | |||
526 | ||||
527 | =item L<Throwable> | |||
528 | ||||
529 | A lightweight role for rolling your own exception classes. | |||
530 | ||||
531 | =item L<Error> | |||
532 | ||||
533 | Exception object implementation with a C<try> statement. Does not localize | |||
534 | C<$@>. | |||
535 | ||||
536 | =item L<Exception::Class::TryCatch> | |||
537 | ||||
538 | Provides a C<catch> statement, but properly calling C<eval> is your | |||
539 | responsibility. | |||
540 | ||||
541 | The C<try> keyword pushes C<$@> onto an error stack, avoiding some of the | |||
542 | issues with C<$@>, but you still need to localize to prevent clobbering. | |||
543 | ||||
544 | =back | |||
545 | ||||
546 | =head1 LIGHTNING TALK | |||
547 | ||||
548 | I gave a lightning talk about this module, you can see the slides (Firefox | |||
549 | only): | |||
550 | ||||
551 | L<http://nothingmuch.woobling.org/talks/takahashi.xul?data=yapc_asia_2009/try_tiny.txt> | |||
552 | ||||
553 | Or read the source: | |||
554 | ||||
555 | L<http://nothingmuch.woobling.org/talks/yapc_asia_2009/try_tiny.yml> | |||
556 | ||||
557 | =head1 VERSION CONTROL | |||
558 | ||||
559 | L<http://github.com/nothingmuch/try-tiny/> | |||
560 | ||||
561 | =head1 AUTHOR | |||
562 | ||||
563 | Yuval Kogman E<lt>nothingmuch@woobling.orgE<gt> | |||
564 | ||||
565 | =head1 COPYRIGHT | |||
566 | ||||
567 | Copyright (c) 2009 Yuval Kogman. All rights reserved. | |||
568 | This program is free software; you can redistribute | |||
569 | it and/or modify it under the terms of the MIT license. | |||
570 | ||||
571 | =cut | |||
572 |