• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Catch Me If You Can: Sugary Exception Handling in Perl
 

Catch Me If You Can: Sugary Exception Handling in Perl

on

  • 5,138 views

Exception handling in perl is currenlty far from perfect. eval leaves a lot to be desired. Lots of {dark,cpan} code is rife with pottential code that could interfere with $@ ...

Exception handling in perl is currenlty far from perfect. eval leaves a lot to be desired. Lots of {dark,cpan} code is rife with pottential code that could interfere with $@

TryCatch (on CPAN now) fixes this through the magic of Devel::Declare.

Breifly address what's wrong with eval, what I/we'd like, and then finally how it was done using Devel::Declare

Statistics

Views

Total Views
5,138
Views on SlideShare
5,127
Embed Views
11

Actions

Likes
4
Downloads
74
Comments
1

2 Embeds 11

http://www.slideshare.net 10
http://www.mefeedia.com 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

CC Attribution-NonCommercial-ShareAlike LicenseCC Attribution-NonCommercial-ShareAlike LicenseCC Attribution-NonCommercial-ShareAlike License

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel

11 of 1 previous next

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
  • Are you familiar with Exception::Class? Check my blog: codeunquote.blogger.com where I have a 5-part series on exception handling starting with basics and ending with Best Practices.

    Exception Handling with Exception::Class is a whole new experience. I have made it part of the coding standards at my firm and it has been a substantial factor in improving code quality.

    Cheers!
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Catch Me If You Can: Sugary Exception Handling in Perl Catch Me If You Can: Sugary Exception Handling in Perl Presentation Transcript

    • EXCEPTION HANDLING IN PERL catch me if you can YAPC EU 2009 = ASH BERLIN ‹ %DEVEL DECLARE / SCOPE UPPER ‹ eASH BERLIN aASH BERLIN ½ MST < FLORIAN RAGWITZ / VINCENT PIT £MARK FOWLER / THE O’REILLY CAMEL Tuesday, 11 August 2009
    • Catch Me If You Can: Sugary exception handling with TryCatch.pm Ash Berlin YAPC::EU 2009 – Lison A.K.A The please don’t sue me Title Tuesday, 11 August 2009
    • Perl Sucks! (and what to do about it) Image courtesy of Mark Fowler YAPC::EU 2007 – Vienna Tuesday, 11 August 2009
    • 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
    • eval {}; sucks Tuesday, 11 August 2009
    • eval {}; sucks Tuesday, 11 August 2009
    • 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
    • “But Perl already has exception handling” Lots of Exception::* and Error::* modules Tuesday, 11 August 2009
    • 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
    • I want the Moon on a Stick Tuesday, 11 August 2009
    • I want the Moon on a Stick Tuesday, 11 August 2009
    • Exceptions in JavaScript try { someCallThatDies(); } catch (e if e instanceof Error) {} catch (f if f.length < 10) {} catch (g) { /* otherwise */ } Tuesday, 11 August 2009
    • The same in Perl eval { some_call_that_dies(); }; if (blessed($@) && $@->isa(‘Error’)) { my $e = $@; } elsif (len($@) < 10 ) { my $f = $@; } elsif ($@) { my $g = $@; } Tuesday, 11 August 2009
    • The same in Perl Done 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
    • That’s a lot to write every time Not very DRY Tuesday, 11 August 2009
    • Using Error.pm use Error qw(:try); try { some_call_that_dies(); } catch Error with { my $e = shift; } Looking good so far… Tuesday, 11 August 2009
    • Using Error.pm use Error qw(:try); try { some_call_that_dies(); } catch Error with { my $e = shift; } otherwise { my $f = shift; if (length($f) < 10) { } else { my $g = $f; } } Less good :( Tuesday, 11 August 2009
    • 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
    • TryCatch.pm use TryCatch; try { some_call_that_dies(); } catch (Error $e) {} catch ($f where {length < 10}) {} catch ($g) {} # otherwise Tuesday, 11 August 2009
    • 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
    • Try syntax • try keyword • Followed by a block • That was easy :) Tuesday, 11 August 2009
    • Catch syntax • catch keyword • Followed by an optional signature: (MyError $e where { } ) • Followed by a block. Tuesday, 11 August 2009
    • Catch Sig syntax (MyError $e where { } ) • 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] Tuesday, 11 August 2009
    • Catch Sig syntax (MyError $e where { } ) • $e is the variable name for the error • Will be created as “my $e” in the block • A variable name is required Tuesday, 11 August 2009
    • Catch Sig syntax (MyError $e where { } ) • Constraint (not type constraint) • $_ is the error being tested. • Much like grep or map, return truthy value • PPI used to just get ‘everything in {}’ Tuesday, 11 August 2009
    • 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
    • TryCatch example 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
    • TryCatch example sub foo { This will return a value from try { foo, not just the try/eval die MyError->new($_[0]) if $_[1] eq “class”; i.e. use return natually die $_[0] if $_[1] eq “plain”; return “value”; } catch (MyError $e) { } catch ($e where { /No Cheese!/ }) { } catch ($e) { } # otherwise } Tuesday, 11 August 2009
    • TryCatch example sub foo { Moose type constraints try { handle the “is this a blessed die MyError->new($_[0]) object” and similar checks 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
    • TryCatch example sub foo { If this wasn’t here, and the try { plain error was thrown, it die MyError->new($_[0]) would get re-thrown. 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
    • xkcd.com Implementation Here Be (anthropomorphic) Dragons Tuesday, 11 August 2009
    • 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
    • Source Filters package ShootMeInTheHead; use Moose; use Switch; sub foo {   my ($variable) = @_;   return $variable + 1; } sub bar {   my ($variable) = @_;   return $variab1e + 1; Global symbol "$variab1e" requires } explicit package name at line 18. } Tuesday, 11 August 2009
    • Source Filters package ShootMeInTheHead; use Moose; use Switch; # load switch statement sub foo {   my ($variable) = @_;   return $variable + 1; } sub bar {   my ($variable) = @_;   return $variab1e + 1; Global symbol "$variab1e" requires } explicit package name at line 18. } Tuesday, 11 August 2009
    • Source Filters package ShootMeInTheHead; use Moose; use Switch; # load switch statement sub foo {   my ($variable) = @_;   return $variable + 1; } sub bar {   my ($variable) = @_;   return $variab1e + 1; Global symbol "$variab1e" requires } explicit package name at line 14. } Tuesday, 11 August 2009
    • 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
    • Using Devel::Declare • When perl parses catch ($e) { my $foo = … • Sees catch as a OP_CONST Tuesday, 11 August 2009
    • Using Devel::Declare • When perl parses catch ($e) { my $foo = … • Calls PL_check[OP_CONST] Tuesday, 11 August 2009
    • Using Devel::Declare • When perl parses catch ($e) { my $foo = … • Calls PL_check[OP_CONST] • Devel::Declare hooks this • And calls back into perl code Tuesday, 11 August 2009
    • Using Devel::Declare • When perl parses catch ($e) { my $foo = … • Calls PL_check[OP_CONST] • Devel::Declare lets us change this into… catch; { if (my $e = $@) { my $foo = … Tuesday, 11 August 2009
    • 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
    • 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
    • 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
    • In short, lots of scary XS. Tuesday, 11 August 2009
    • use TryCatch; try { some_call_that_dies(); } catch (Error $e) {} catch ($f where {length < 10}) {} catch ($g) {} # otherwise Tuesday, 11 August 2009
    • 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
    • hu∙bris noun excessive pride or self-confidence. • (in Greek tragedy) excessive pride toward or defiance of the gods, leading to nemesis. DERIVATIVES hu∙bris∙tic adjective ORIGIN Greek. Ash Berlin <ash@cpan.org> Questions? Tuesday, 11 August 2009