SlideShare a Scribd company logo
1 of 47
Download to read offline
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

More Related Content

Viewers also liked

Textual analysis of catch me if you can
Textual analysis of catch me if you canTextual analysis of catch me if you can
Textual analysis of catch me if you canpatrickmetry
 
CATCH US IF YOU CAN - Anna Isha
CATCH US IF YOU CAN - Anna IshaCATCH US IF YOU CAN - Anna Isha
CATCH US IF YOU CAN - Anna IshaAnna Isha
 
Top 10 Most Eaten Foods In The World
Top 10 Most Eaten Foods In The WorldTop 10 Most Eaten Foods In The World
Top 10 Most Eaten Foods In The WorldEason Chan
 
Oscars 2016: Winners and Highlights
Oscars 2016: Winners and  HighlightsOscars 2016: Winners and  Highlights
Oscars 2016: Winners and Highlightsmaditabalnco
 
Can We Assess Creativity?
Can We Assess Creativity?Can We Assess Creativity?
Can We Assess Creativity?John Spencer
 

Viewers also liked (6)

Textual analysis of catch me if you can
Textual analysis of catch me if you canTextual analysis of catch me if you can
Textual analysis of catch me if you can
 
CATCH US IF YOU CAN - Anna Isha
CATCH US IF YOU CAN - Anna IshaCATCH US IF YOU CAN - Anna Isha
CATCH US IF YOU CAN - Anna Isha
 
LONDON
LONDONLONDON
LONDON
 
Top 10 Most Eaten Foods In The World
Top 10 Most Eaten Foods In The WorldTop 10 Most Eaten Foods In The World
Top 10 Most Eaten Foods In The World
 
Oscars 2016: Winners and Highlights
Oscars 2016: Winners and  HighlightsOscars 2016: Winners and  Highlights
Oscars 2016: Winners and Highlights
 
Can We Assess Creativity?
Can We Assess Creativity?Can We Assess Creativity?
Can We Assess Creativity?
 

Recently uploaded

Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsRoshan Dwivedi
 
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...Principled Technologies
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024The Digital Insurer
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
Top 10 Most Downloaded Games on Play Store in 2024
Top 10 Most Downloaded Games on Play Store in 2024Top 10 Most Downloaded Games on Play Store in 2024
Top 10 Most Downloaded Games on Play Store in 2024SynarionITSolutions
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MIND CTI
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUK Journal
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FMESafe Software
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdflior mazor
 

Recently uploaded (20)

Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
 
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Top 10 Most Downloaded Games on Play Store in 2024
Top 10 Most Downloaded Games on Play Store in 2024Top 10 Most Downloaded Games on Play Store in 2024
Top 10 Most Downloaded Games on Play Store in 2024
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 

Catch Me If You Can: Sugary Exception Handling in Perl

  • 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. 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. Perl Sucks! (and what to do about it) Image courtesy of Mark Fowler YAPC::EU 2007 – Vienna Tuesday, 11 August 2009
  • 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. eval {}; sucks Tuesday, 11 August 2009
  • 6. eval {}; sucks Tuesday, 11 August 2009
  • 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. “But Perl already has exception handling” Lots of Exception::* and Error::* modules Tuesday, 11 August 2009
  • 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. I want the Moon on a Stick Tuesday, 11 August 2009
  • 11. I want the Moon on a Stick Tuesday, 11 August 2009
  • 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. 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. 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. That’s a lot to write every time Not very DRY Tuesday, 11 August 2009
  • 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. 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. 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. 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. 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. Try syntax • try keyword • Followed by a block • That was easy :) Tuesday, 11 August 2009
  • 22. Catch syntax • catch keyword • Followed by an optional signature: (MyError $e where { } ) • Followed by a block. Tuesday, 11 August 2009
  • 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. 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. 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. 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. 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. 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. 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. 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. xkcd.com Implementation Here Be (anthropomorphic) Dragons Tuesday, 11 August 2009
  • 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. 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. 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. 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. 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. Using Devel::Declare • When perl parses catch ($e) { my $foo = … • Sees catch as a OP_CONST Tuesday, 11 August 2009
  • 38. Using Devel::Declare • When perl parses catch ($e) { my $foo = … • Calls PL_check[OP_CONST] Tuesday, 11 August 2009
  • 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. 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. 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. 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. 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. In short, lots of scary XS. Tuesday, 11 August 2009
  • 45. use TryCatch; try { some_call_that_dies(); } catch (Error $e) {} catch ($f where {length < 10}) {} catch ($g) {} # otherwise Tuesday, 11 August 2009
  • 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. 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