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