![Page 1: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/1.jpg)
YAPC EU 2009 = ASH BERLIN ‹ %DEVEL DECLARE / SCOPE UPPER ‹eASH BERLIN aASH BERLIN ½ MST < FLORIAN RAGWITZ / VINCENT PIT
£MARK FOWLER / THE O’REILLY CAMEL
EXCEPTION HANDLING IN PERL
if you cancatch me
Tuesday, 11 August 2009
![Page 2: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/2.jpg)
Catch Me If You Can:Sugary exception handling with TryCatch.pm
Ash BerlinYAPC::EU 2009 – Lison
A.K.A The please don’t sue me Title
Tuesday, 11 August 2009
![Page 3: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/3.jpg)
Perl Sucks!(and what to do about it)
Image courtesy of Mark Fowler
YAPC::EU 2007 – Vienna
Tuesday, 11 August 2009
![Page 4: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/4.jpg)
Perl Sucks?
• Of course it does, it’s software
• Installing Modules is hard
• Perl programs are just scripts
• Its Exception handling is hateful
Tuesday, 11 August 2009
![Page 5: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/5.jpg)
eval {};sucks
Tuesday, 11 August 2009
![Page 6: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/6.jpg)
eval {};sucks
Tuesday, 11 August 2009
![Page 7: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/7.jpg)
eval sucks
• Sucky syntax
• Easy to get (subtly) wrong.
• return doesn’t work as expected
• eval BLOCK vs eval EXPR
• $@ is global
Tuesday, 11 August 2009
![Page 8: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/8.jpg)
“But Perl already has exception handling”
Lots of Exception::* and Error::* modules
Tuesday, 11 August 2009
![Page 9: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/9.jpg)
None of them Perfect
• Some are just an exception framework
• Good; doesn’t solve catching problem
• Catching errors shouldn’t be hard
Tuesday, 11 August 2009
![Page 10: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/10.jpg)
I want the Moon on a Stick
Tuesday, 11 August 2009
![Page 11: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/11.jpg)
I want the Moon on a Stick
Tuesday, 11 August 2009
![Page 12: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/12.jpg)
Exceptions in JavaScript
try { someCallThatDies();}catch (e if e instanceof Error) {}catch (f if f.length < 10) {}catch (g) { /* otherwise */ }
Tuesday, 11 August 2009
![Page 13: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/13.jpg)
The same in Perl
if (blessed($@) && $@->isa(‘Error’)) { my $e = $@;}elsif (len($@) < 10 ) { my $f = $@; }elsif ($@) { my $g = $@;}
eval { some_call_that_dies();};
Tuesday, 11 August 2009
![Page 14: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/14.jpg)
The same in PerlDone properly
{ local $@; eval { some_call_that_dies(); }; if (my $_e = $@) { if (blessed($_e) && $_e->isa(‘Error’)) { my $e = $_e; } elsif (len($_e) < 10 ) { my $f = $_e; } else { my $g = $_e; } }}
Tuesday, 11 August 2009
![Page 15: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/15.jpg)
That’s a lot to write every time
Not very DRY
Tuesday, 11 August 2009
![Page 16: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/16.jpg)
Using Error.pm
Looking good so far…
use Error qw(:try);try { some_call_that_dies(); }catch Error with { my $e = shift;}
Tuesday, 11 August 2009
![Page 17: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/17.jpg)
Using Error.pm
otherwise { my $f = shift; if (length($f) < 10) { } else { my $g = $f; }} Less good :(
use Error qw(:try);try { some_call_that_dies(); }catch Error with { my $e = shift;}
Tuesday, 11 August 2009
![Page 18: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/18.jpg)
Problems with Error.pm
• (Not to single it out as bad)
• Its Exception Object class
• AND try/catch implementations
• sub {} closures are slow
• Speed for error free path is important
Tuesday, 11 August 2009
![Page 19: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/19.jpg)
TryCatch.pm
use TryCatch;try { some_call_that_dies();}catch (Error $e) {}catch ($f where {length < 10}) {}catch ($g) {} # otherwise
Tuesday, 11 August 2009
![Page 20: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/20.jpg)
TryCatch syntax
• try must be followed by a block
• Followed by zero or more catch clauses
• catch may be followed by a signature
• catch must also be followed by a block
Tuesday, 11 August 2009
![Page 21: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/21.jpg)
Try syntax
• try keyword
• Followed by a block
• That was easy :)
Tuesday, 11 August 2009
![Page 22: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/22.jpg)
Catch syntax
• catch keyword
• Followed by an optional signature:
(MyError $e where { } )
• Followed by a block.
Tuesday, 11 August 2009
![Page 23: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/23.jpg)
Catch Sig syntax
• MyError is any valid Moose type constraint
• Optional
• Uses MooseX::Types for preference
• Else falls back to Moose’s string parsing
• Never quoted, always bare
• Example:
Str|ArrayRef[MyError]
(MyError $e where { } )
Tuesday, 11 August 2009
![Page 24: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/24.jpg)
Catch Sig syntax
• $e is the variable name for the error
• Will be created as “my $e” in the block
• A variable name is required
(MyError $e where { } )
Tuesday, 11 August 2009
![Page 25: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/25.jpg)
Catch Sig syntax
• Constraint (not type constraint)
• $_ is the error being tested.
• Much like grep or map, return truthy value
• PPI used to just get ‘everything in {}’
(MyError $e where { } )
Tuesday, 11 August 2009
![Page 26: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/26.jpg)
Syntax Notes
• try can be nested as deep as you like
• You can use return to exit the sub.
• No finally. Yet. It’s on my TODO
Tuesday, 11 August 2009
![Page 27: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/27.jpg)
TryCatch examplesub foo {
try { die MyError->new($_[0]) if $_[1] eq “class”; die $_[0] if $_[1] eq “plain”;
return “value”;}catch (MyError $e) { }catch ($e where { /No Cheese!/ }) { }catch ($e) { } # otherwise
}
Tuesday, 11 August 2009
![Page 28: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/28.jpg)
TryCatch examplesub foo {
try { die MyError->new($_[0]) if $_[1] eq “class”; die $_[0] if $_[1] eq “plain”;
return “value”;}catch (MyError $e) { }catch ($e where { /No Cheese!/ }) { }catch ($e) { } # otherwise
}
This will return a value from foo, not just the try/eval
i.e. use return natually
Tuesday, 11 August 2009
![Page 29: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/29.jpg)
sub foo {try { die MyError->new($_[0]) if $_[1] eq “class”; die $_[0] if $_[1] eq “plain”;
return “value”;}catch (MyError $e) { }catch ($e where { /No Cheese!/ }) { }catch ($e) { } # otherwise
}
TryCatch exampleMoose type constraints
handle the “is this a blessed object” and similar checks
Tuesday, 11 August 2009
![Page 30: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/30.jpg)
TryCatch exampleIf this wasn’t here, and the plain error was thrown, it
would get re-thrown.
sub foo {try { die MyError->new($_[0]) if $_[1] eq “class”; die $_[0] if $_[1] eq “plain”;
return “value”;}catch (MyError $e) { }catch ($e where { /No Cheese!/ }) { }catch ($e) { } # otherwise
}
Tuesday, 11 August 2009
![Page 31: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/31.jpg)
ImplementationHere Be (anthropomorphic) Dragons
xkcd.com
Tuesday, 11 August 2009
![Page 32: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/32.jpg)
Source Filters
• Have to look through the entire source
• And only change the bits they want.
• Perl is notoriously hard to parse
• Can cause odd bugs:
Tuesday, 11 August 2009
![Page 33: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/33.jpg)
package ShootMeInTheHead;
use Moose;use Switch;
sub foo { my ($variable) = @_; return $variable + 1;}sub bar { my ($variable) = @_; return $variab1e + 1;}}
Source Filters
Global symbol "$variab1e" requires explicit package name at line 18.
Tuesday, 11 August 2009
![Page 34: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/34.jpg)
package ShootMeInTheHead;
use Moose;use Switch;
sub foo { my ($variable) = @_; return $variable + 1;}sub bar { my ($variable) = @_; return $variab1e + 1;}}
Source Filters
Global symbol "$variab1e" requires explicit package name at line 18.
# load switch statement
Tuesday, 11 August 2009
![Page 35: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/35.jpg)
package ShootMeInTheHead;
use Moose;use Switch;
sub foo { my ($variable) = @_; return $variable + 1;}sub bar { my ($variable) = @_; return $variab1e + 1;}}
Source Filters
Global symbol "$variab1e" requires explicit package name at line 14.
# load switch statement
Tuesday, 11 August 2009
![Page 36: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/36.jpg)
Devel::Declare
• Lets you change the source Perl is about to compile
• Like a source filter
• But far less fragile.
• Key-hole source filter effect.
Tuesday, 11 August 2009
![Page 37: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/37.jpg)
• When perl parses
catch ($e) { my $foo = …
Using Devel::Declare
• Sees catch as a OP_CONST
Tuesday, 11 August 2009
![Page 38: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/38.jpg)
• When perl parses
catch ($e) { my $foo = …
Using Devel::Declare
• Calls PL_check[OP_CONST]
Tuesday, 11 August 2009
![Page 39: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/39.jpg)
• When perl parses
catch ($e) { my $foo = …
Using Devel::Declare
• Calls PL_check[OP_CONST]
• Devel::Declare hooks this
• And calls back into perl code
Tuesday, 11 August 2009
![Page 40: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/40.jpg)
• When perl parses
catch ($e) { my $foo = …
Using Devel::Declare
• Calls PL_check[OP_CONST]
• Devel::Declare lets us change this into…
catch; { if (my $e = $@) { my $foo = …
Tuesday, 11 August 2009
![Page 41: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/41.jpg)
Using Devel::Declare
• TryCatch doesn’t quite produce that code
• But it shows how things work
• Also uses B::Hooks::OP::{Check,PPaddr} to solve the return problem
Tuesday, 11 August 2009
![Page 42: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/42.jpg)
The return problem
• Simple:
sub foo { eval { return $val }; 1}
• Would be nice if it returned from foo
• vincent++ # Scope::Upper
• unwind HERE, @values;
Tuesday, 11 August 2009
![Page 43: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/43.jpg)
The return problem
• Typing return would be better than unwind
• Install an extra PL_check hook on OP_RETURN
• And install a custom op handler
• Makes return inside try behave like unwind
Tuesday, 11 August 2009
![Page 44: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/44.jpg)
In short, lots of scary XS.
Tuesday, 11 August 2009
![Page 45: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/45.jpg)
use TryCatch;
try { some_call_that_dies();}catch (Error $e) {}catch ($f where {length < 10}) {}catch ($g) {} # otherwise
Tuesday, 11 August 2009
![Page 46: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/46.jpg)
use TryCatch;
try ;{ local $@; eval { some_call_that_dies(); }; $TryCatch::Error = $@; }if ($TryCatch::Error) { if (TryCatch->check_tc('Error')){ my $e = $TryCatch::Error; } elsif (do {local $_ = $TryCatch::Error; length($_) < 10 }) { my $f = $TryCatch::Error; } elsif (1){ my $g = $TryCatch::Error; } # otherwise else { $@ = $TryCatch::Error; die } }
Tuesday, 11 August 2009
![Page 47: Catch Me If You Can: Sugary Exception Handling in Perl](https://reader030.vdocuments.us/reader030/viewer/2022020122/5549b9c3b4c905e5048b4d30/html5/thumbnails/47.jpg)
hu∙bris |ˈhjuːbrɪs|nounexcessive pride or self-confidence.
• (in Greek tragedy) excessive pride toward or defiance of the gods, leading to nemesis.
DERIVATIVEShu∙bris∙tic |(h)yoōˈbristik| |(h)juˈbrɪstɪk| |-ˈbrɪstɪk| adjective
ORIGIN Greek.
Questions?<[email protected]>
Ash Berlin
Tuesday, 11 August 2009