0
EXCEPTION HANDLING IN PERL

        catch me                                                 if you can
                  ...
Catch Me If You Can:
                Sugary exception handling with TryCatch.pm

                                      Ash...
Perl Sucks!
                              (and what to do about it)




                                           Image c...
Perl Sucks?

                    • Of course it does, it’s software
                    • Installing Modules is hard
     ...
eval {};
                           sucks


Tuesday, 11 August 2009
eval {};
                           sucks


Tuesday, 11 August 2009
eval sucks

                    • Sucky syntax
                    • Easy to get (subtly) wrong.
                    • ret...
“But Perl already has
                          exception handling”
                           Lots of Exception::* and Er...
None of them Perfect

                    • Some are just an exception framework
                    • Good; doesn’t solve...
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();
                ...
The same in Perl
                          eval {
                             some_call_that_dies();
                    ...
The same in Perl
                                   Done properly
                          {
                            ...
That’s a lot to
                          write every time
                               Not very DRY




Tuesday, 11 Aug...
Using Error.pm

                          use Error qw(:try);
                          try { some_call_that_dies(); }
   ...
Using Error.pm
                          use Error qw(:try);
                          try { some_call_that_dies(); }
    ...
Problems with Error.pm

                    • (Not to single it out as bad)
                    • Its Exception Object cla...
TryCatch.pm
                          use TryCatch;
                          try {
                            some_call_...
TryCatch syntax

                    • try must be followed by a block
                    • Followed by zero or more catc...
Try syntax

                    • try keyword
                    • Followed by a block
                    • That was eas...
Catch syntax

                    • catch keyword
                    • Followed by an optional signature:
               ...
Catch Sig syntax
                               (MyError $e where { } )
                    •     MyError is any valid Moo...
Catch Sig syntax
                           (MyError $e where { } )




                    • $e is the variable name for ...
Catch Sig syntax
                           (MyError $e where { } )



                    • Constraint (not type constrai...
Syntax Notes

                    • try can be nested as deep as you like
                    • You can use return to exit...
TryCatch example
                sub foo {
                   try {
                     die MyError->new($_[0])
         ...
TryCatch example
                sub foo {                               This will return a value from
                   ...
TryCatch example
                sub foo {                                   Moose type constraints
                   try...
TryCatch example
                sub foo {                                 If this wasn’t here, and the
                  ...
xkcd.com




                          Implementation
                          Here Be (anthropomorphic) Dragons
Tuesday,...
Source Filters

                    • Have to look through the entire source
                    • And only change the bit...
Source Filters
                package ShootMeInTheHead;
                use Moose;
                use Switch;




      ...
Source Filters
                package ShootMeInTheHead;
                use Moose;
                use Switch;

         ...
Source Filters
                package ShootMeInTheHead;
                use Moose;
                use Switch;

         ...
Devel::Declare

                    • Lets you change the source Perl is about to
                          compile
      ...
Using Devel::Declare
                    • When perl parses
                          catch ($e) { my $foo = …

          ...
Using Devel::Declare
                    • When perl parses
                          catch ($e) { my $foo = …

          ...
Using Devel::Declare
                    • When perl parses
                          catch ($e) { my $foo = …

          ...
Using Devel::Declare
                    • When perl parses
                          catch ($e) { my $foo = …

          ...
Using Devel::Declare

                    • TryCatch doesn’t quite produce that code
                    • But it shows ho...
The return problem

                    • Simple:
                          sub foo { eval { return $val }; 1}

          ...
The return problem

                    • Typing return would be better than unwind
                    • Install an extra...
In short, lots of scary
                                    XS.
Tuesday, 11 August 2009
use TryCatch;

                try {
                  some_call_that_dies();
                }
                catch (Err...
use TryCatch;

                try ;{
                  local $@;
                  eval {
                     some_call_...
hu∙bris
       noun
       excessive pride or self-confidence.
          • (in Greek tragedy) excessive pride toward or defi...
Upcoming SlideShare
Loading in...5
×

Catch Me If You Can: Sugary Exception Handling in Perl

3,366

Published on

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

Published in: Technology, Business
1 Comment
5 Likes
Statistics
Notes
No Downloads
Views
Total Views
3,366
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
78
Comments
1
Likes
5
Embeds 0
No embeds

No notes for slide

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

  1. 1. 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
  2. 2. 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
  3. 3. Perl Sucks! (and what to do about it) Image courtesy of Mark Fowler YAPC::EU 2007 – Vienna Tuesday, 11 August 2009
  4. 4. 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
  5. 5. eval {}; sucks Tuesday, 11 August 2009
  6. 6. eval {}; sucks Tuesday, 11 August 2009
  7. 7. 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
  8. 8. “But Perl already has exception handling” Lots of Exception::* and Error::* modules Tuesday, 11 August 2009
  9. 9. 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
  10. 10. I want the Moon on a Stick Tuesday, 11 August 2009
  11. 11. I want the Moon on a Stick Tuesday, 11 August 2009
  12. 12. Exceptions in JavaScript try { someCallThatDies(); } catch (e if e instanceof Error) {} catch (f if f.length < 10) {} catch (g) { /* otherwise */ } Tuesday, 11 August 2009
  13. 13. 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
  14. 14. 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
  15. 15. That’s a lot to write every time Not very DRY Tuesday, 11 August 2009
  16. 16. 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
  17. 17. 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
  18. 18. 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
  19. 19. TryCatch.pm use TryCatch; try { some_call_that_dies(); } catch (Error $e) {} catch ($f where {length < 10}) {} catch ($g) {} # otherwise Tuesday, 11 August 2009
  20. 20. 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
  21. 21. Try syntax • try keyword • Followed by a block • That was easy :) Tuesday, 11 August 2009
  22. 22. Catch syntax • catch keyword • Followed by an optional signature: (MyError $e where { } ) • Followed by a block. Tuesday, 11 August 2009
  23. 23. 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
  24. 24. 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
  25. 25. 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
  26. 26. 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
  27. 27. 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
  28. 28. 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
  29. 29. 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
  30. 30. 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
  31. 31. xkcd.com Implementation Here Be (anthropomorphic) Dragons Tuesday, 11 August 2009
  32. 32. 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
  33. 33. 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
  34. 34. 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
  35. 35. 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
  36. 36. 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
  37. 37. Using Devel::Declare • When perl parses catch ($e) { my $foo = … • Sees catch as a OP_CONST Tuesday, 11 August 2009
  38. 38. Using Devel::Declare • When perl parses catch ($e) { my $foo = … • Calls PL_check[OP_CONST] Tuesday, 11 August 2009
  39. 39. 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
  40. 40. 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
  41. 41. 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
  42. 42. 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
  43. 43. 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
  44. 44. In short, lots of scary XS. Tuesday, 11 August 2009
  45. 45. use TryCatch; try { some_call_that_dies(); } catch (Error $e) {} catch ($f where {length < 10}) {} catch ($g) {} # otherwise Tuesday, 11 August 2009
  46. 46. 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
  47. 47. 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
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×