What is the best way to deal with exceptions threw in a method chaining in Perl? I want to assign a value of 0 or undef if any of the methods chained throw an exception
You can write a scalar method that will wrap a method chain in error handling:
my $try = sub {
@_ > 1 or return bless {ok => $_[0]} => 'Try';
my ($self, $method) = splice @_, 0, 2;
my $ret;
eval {
$ret = $self->$method(@_);
1} or return bless {error => $@} => 'Try';
bless {ok => $ret} => 'Try'
};
{package Try;
use overload fallback => 1, '""' => sub {$_[0]{ok}};
sub AUTOLOAD {
my ($method) = our $AUTOLOAD =~ /([^:]+)$/;
$_[0]{ok} ? $_[0]{ok}->$try($method, @_[1..$#_]) : $_[0]
}
sub DESTROY {}
sub error {$_[0]{error}}
}
to use it:
{package Obj;
sub new {bless [0]}
sub set {$_[0][0] = $_[1]; $_[0]}
sub add {$_[0][0] += ($_[1] || 1); $_[0]}
sub show {print "Obj: $_[0][0]\n"}
sub dies {die "an error occured"}
}
my $obj = Obj->new;
say "ok 1" if $obj->$try(set => 5)->add->add->show; # prints "Obj 7"
# and "ok 1"
say "ok 2" if $obj->$try('dies')->add->add->show; # prints nothing
say $obj->$try('dies')->add->add->show->error; # prints "an error occured..."
The first line of the $try
method also allows the following syntax:
say "ok 3" if $obj->$try->set(5)->add->add->show;