Perl Module(s) Of The Week - 2019 Week 09 - Carp and Carp::Always

This week we will look into three Perl modules, Carp and Carp::Always that alters or enhances the default behaviours of error handling using both `warn` and `die` function. Basically both functions will raise a warning and write an error message to standard error (STDERR) but `die` will throw an exception by exiting from the program through `exit` function.

The `die` function is commonly used when opening a file. When the opened file is not found, an exception will be thrown with an error displayed to STDERR and termination of the program. Example below illustrates this. We can substitute `die` with `warn` but that is not a good practice as open a missing file disrupts the normal flow of the program and an exception should be raised and the program should be terminated.
open(my $fh, "<", "input.txt")
    or die "Can't open < input.txt: $!";

Installation is straightforward. As usual.
$ cpanm Carp Carp::Always

What kind of different behaviours that `Carp` module provides? Let look at the below code example consists of a module `Foo.pm` and the calling script `test.pl`.
# Foo.pm
package Foo;
use Carp;

sub twarn { warn "test warn"};
sub tcarp { carp "test carp"};

1;

# test.pl
use lib ".";
use Foo;

Foo::twarn();
Foo::tcarp();

Running the above code will give us below output. Upon an exception, the `warn` function reports the file name (`Foo.pm`) and the line number (`line 4`) where the error occurred. Using `carp` function with verbosity enabled, the function shows additional details on the caller's file name (`test.pl`) and line number (`line 5`). If you're writing a Perl's CPAN module or subroutines, using `Carp` module is a preferred choice as the library user (the caller) is more interested in finding where in their own code that causing the exception.
$ perl -MCarp=verbose test.pl 
test warn at Foo.pm line 4.
test carp at Foo.pm line 5.
        Foo::tcarp() called at test.pl line 5

The `Carp` module provides several common functions that wrapped around both `warn` and `die` functions.

(1) `carp` - `warn` of errors (from perspective of caller).
(2) `cluck` - `warn` of errors with stack backtrace.
(3) `croak` - `die` of errors (from perspective of caller)
(4) `confess - `die` of errors with stack backtrace

What if you don't want or can't changed any existing code that uses the `warn` and `die` function but still want behaviour provided by `Carp` module with backtrace? This is where `Carp::Always` module comes in as shown in the result below.
$ perl -MCarp::Always bar.pl               
test warn at Foo.pm line 4.
        Foo::twarn() called at bar.pl line 4
test carp at Foo.pm line 5.
        Foo::tcarp() called at bar.pl line 5

No comments:

Post a Comment