After recently installing perl v5.38,
I stumbled upon some cool improvements to Perl's built-in try/catch syntax while watching the excellent
What's new in Perl v5.38
youtube talk, delivered by Paul "LeoNerd" Evans at TPRC 2023 Toronto.
New perl 5.38 use feature 'try'
- perl v5.34 added try/catch syntax based on CPAN module Syntax::Keyword::Try
- perl v5.36 added "finally" blocks to try/catch, also inspired by Syntax::Keyword::Try
- perl v5.36 added use feature 'defer', allowing you to create defer blocks that run at the time that execution leaves the block it's declared inside (which seems to be inspired by the classic RAII programming idiom)
- use v5.38 implies use feature 'try'
Update: note that try-catch feature is no longer experimental with perl v5.40 - its use without finally blocks no longer prints a warning but it still must be enabled with the 'try' feature.
Some perldoc References
- die - is how you throw exceptions in Perl
- eval - used to execute a little Perl program, trapping any errors encountered so they don't crash the calling program
- Carp - alternative warn and die for modules
- autodie - Replace functions with ones that succeed or die with lexical scope
- Fatal - Replace functions with equivalents which succeed or die
To get a feel for how all this works in practice, I created a simple example,
consisting of two files in a scratch directory, TestTry.pm and trytest.pl, shown below.
TestTry.pm
package TestTry;
use strict;
use warnings;
print "TestTry: module load\n";
sub life {
my $n = shift;
defined($n) or die "error: no argument provided";
print "TestTry::life n='$n'\n";
$n =~ /^\d+$/ or die "input error: '$n' must consist of digits only
+";
$n == 42 or die "Sadly there is no meaning in your life (n=$n)
+";
print "TestTry: congrats, your life has meaning!\n";
print "TestTry::life end\n";
}
1;
trytest.pl
# trytest.pl - a simple test of new perl 5.38 try syntax:
# Put TestTry.pm in same dir as trytest.pl and run with:
# perl -I . trytest.pl
# Note: use v5.38 implies use strict and warnings
use v5.38;
# use feature 'try'; # throws 'try/catch is experimental' warnings
+(update: works with perl v5.40.0 if you are not using finally blocks)
use experimental 'try';
use TestTry;
sub do_one {
my $number = shift;
try {
TestTry::life($number);
}
catch ($e) {
chomp $e;
print "trytest: caught '$e'\n";
}
finally {
print "trytest: in finally block\n";
}
}
print "trytest: start\n";
do_one("invalid");
do_one(13);
do_one(42);
print "trytest: end\n";
Example run
With that done, assuming you have perl 5.38 installed, you can run:
$ perl -I . trytest.pl
TestTry: module load
trytest: start
TestTry::life n='invalid'
trytest: caught 'input error: 'invalid' must consist of digits only at
+ TestTry.pm line 11.'
trytest: in finally block
TestTry::life n='13'
trytest: caught 'Sadly there is no meaning in your life (n=13) at Test
+Try.pm line 12.'
trytest: in finally block
TestTry::life n='42'
TestTry: congrats, your life has meaning!
TestTry::life end
trytest: in finally block
trytest: end
Summary
I really like this new try/catch syntax and am looking forward to Perl
providing built-in exception handling without having to install CPAN modules,
such as Try::Tiny and TryCatch.
Remembering the smartmatch/Switch debacle, I'm also a fan of this new gentler way
of introducing experimental new features into the Perl core.
Reference
Exceptions and Error Handling References
See Also
Updated: Added "See Also" section. Tested with perl v5.40.0; added comment re 'try/catch is experimental' warnings.