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

UiPath Platform: The Backend Engine Powering Your Automation - Session 1
UiPath Platform: The Backend Engine Powering Your Automation - Session 1UiPath Platform: The Backend Engine Powering Your Automation - Session 1
UiPath Platform: The Backend Engine Powering Your Automation - Session 1DianaGray10
 
Salesforce Miami User Group Event - 1st Quarter 2024
Salesforce Miami User Group Event - 1st Quarter 2024Salesforce Miami User Group Event - 1st Quarter 2024
Salesforce Miami User Group Event - 1st Quarter 2024SkyPlanner
 
Linked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesLinked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesDavid Newbury
 
20230202 - Introduction to tis-py
20230202 - Introduction to tis-py20230202 - Introduction to tis-py
20230202 - Introduction to tis-pyJamie (Taka) Wang
 
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Will Schroeder
 
Secure your environment with UiPath and CyberArk technologies - Session 1
Secure your environment with UiPath and CyberArk technologies - Session 1Secure your environment with UiPath and CyberArk technologies - Session 1
Secure your environment with UiPath and CyberArk technologies - Session 1DianaGray10
 
Comparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and IstioComparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and IstioChristian Posta
 
UiPath Studio Web workshop series - Day 6
UiPath Studio Web workshop series - Day 6UiPath Studio Web workshop series - Day 6
UiPath Studio Web workshop series - Day 6DianaGray10
 
How Accurate are Carbon Emissions Projections?
How Accurate are Carbon Emissions Projections?How Accurate are Carbon Emissions Projections?
How Accurate are Carbon Emissions Projections?IES VE
 
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPA
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPAAnypoint Code Builder , Google Pub sub connector and MuleSoft RPA
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPAshyamraj55
 
COMPUTER 10 Lesson 8 - Building a Website
COMPUTER 10 Lesson 8 - Building a WebsiteCOMPUTER 10 Lesson 8 - Building a Website
COMPUTER 10 Lesson 8 - Building a Websitedgelyza
 
AI You Can Trust - Ensuring Success with Data Integrity Webinar
AI You Can Trust - Ensuring Success with Data Integrity WebinarAI You Can Trust - Ensuring Success with Data Integrity Webinar
AI You Can Trust - Ensuring Success with Data Integrity WebinarPrecisely
 
UiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation DevelopersUiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation DevelopersUiPathCommunity
 
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...DianaGray10
 
Designing A Time bound resource download URL
Designing A Time bound resource download URLDesigning A Time bound resource download URL
Designing A Time bound resource download URLRuncy Oommen
 
9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding Team9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding TeamAdam Moalla
 
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCostKubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCostMatt Ray
 
UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8DianaGray10
 
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online CollaborationCOMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online Collaborationbruanjhuli
 

Recently uploaded (20)

UiPath Platform: The Backend Engine Powering Your Automation - Session 1
UiPath Platform: The Backend Engine Powering Your Automation - Session 1UiPath Platform: The Backend Engine Powering Your Automation - Session 1
UiPath Platform: The Backend Engine Powering Your Automation - Session 1
 
Salesforce Miami User Group Event - 1st Quarter 2024
Salesforce Miami User Group Event - 1st Quarter 2024Salesforce Miami User Group Event - 1st Quarter 2024
Salesforce Miami User Group Event - 1st Quarter 2024
 
Linked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesLinked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond Ontologies
 
20230202 - Introduction to tis-py
20230202 - Introduction to tis-py20230202 - Introduction to tis-py
20230202 - Introduction to tis-py
 
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
 
Secure your environment with UiPath and CyberArk technologies - Session 1
Secure your environment with UiPath and CyberArk technologies - Session 1Secure your environment with UiPath and CyberArk technologies - Session 1
Secure your environment with UiPath and CyberArk technologies - Session 1
 
Comparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and IstioComparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and Istio
 
UiPath Studio Web workshop series - Day 6
UiPath Studio Web workshop series - Day 6UiPath Studio Web workshop series - Day 6
UiPath Studio Web workshop series - Day 6
 
How Accurate are Carbon Emissions Projections?
How Accurate are Carbon Emissions Projections?How Accurate are Carbon Emissions Projections?
How Accurate are Carbon Emissions Projections?
 
201610817 - edge part1
201610817 - edge part1201610817 - edge part1
201610817 - edge part1
 
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPA
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPAAnypoint Code Builder , Google Pub sub connector and MuleSoft RPA
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPA
 
COMPUTER 10 Lesson 8 - Building a Website
COMPUTER 10 Lesson 8 - Building a WebsiteCOMPUTER 10 Lesson 8 - Building a Website
COMPUTER 10 Lesson 8 - Building a Website
 
AI You Can Trust - Ensuring Success with Data Integrity Webinar
AI You Can Trust - Ensuring Success with Data Integrity WebinarAI You Can Trust - Ensuring Success with Data Integrity Webinar
AI You Can Trust - Ensuring Success with Data Integrity Webinar
 
UiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation DevelopersUiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation Developers
 
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
 
Designing A Time bound resource download URL
Designing A Time bound resource download URLDesigning A Time bound resource download URL
Designing A Time bound resource download URL
 
9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding Team9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding Team
 
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCostKubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
 
UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8
 
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online CollaborationCOMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
 

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