NAME
Try::Chain - Call method, hash and/or array chains with break on undef
VERSION
0.002
SYNOPSIS
The module exports:
try - imported from Try::Tiny
catch - imported from Try::Tiny
finally - imported from Try::Tiny
try_chain - implemented here to call a complete chain or break
$call_m - implemented here to call a method or break
$fetch_i - implemented here to fetch an array index or break
$fetch_k - implemented here to fetch a hash key or break
Import what needed. The following code describes the full import:
use Try::Chain qw( try catch finally try_chain $call_m $fetch_i $fetch_k );
EXAMPLE
Inside of this Distribution is a directory named example. Run this *.pl files.
DESCRIPTION
Call method, hash and/or array chains with break on undef means, that in some cases it is ok to get back nothing late or early.
Problem
In case of method chain like
my $scalar = $obj->foo(1)->bar(2)->baz(3);
my %hash = (
any => 'any',
baz => scalar $obj->foo(1)->bar(2)->baz(3),
);
and foo or bar can return nothing or undef, you get an error: Can't call method ... on an undefined value.
A quick solution is:
my $scalar
= $obj->foo(1)
&& $obj->foo(1)->bar(2)
&& $obj->foo(1)->bar(2)->baz(3);
my %hash = (
any => 'any',
baz => scalar $obj->foo(1)
&& $obj->foo(1)->bar(2)
&& $obj->foo(1)->bar(2)->baz(3),
);
In case of method foo and/or bar is performance critical code it is a bad idea to call the method code more then one time. The the solution looks like this:
my $foo = $obj->foo(1);
my $bar = $foo && $foo->bar(2);
my $scalar = $bar && $bar->baz(3);
my %hash = (
any => 'any',
baz => do {
my $foo = $obj->foo(1);
my $bar = $foo && $foo->bar(2);
$bar && scalar $bar->baz(3);
},
);
Solution
This module allows to call the chain by ignoring all undef errors in block:
my $scalar = try_chain { $obj->foo(1)->bar(2)->baz(3) };
my %hash = (
any => 'any',
baz => scalar try_chain { $obj->foo(1)->bar(2)->baz(3) },
);
Or better step by step?
my $scalar = $obj->$call_m('foo', 1)->$call_m('bar', 2)->$call_m('baz', 3);
my %hash = (
any => 'any',
baz => scalar $obj
->$call_m('foo', 1)
->$call_m('bar', 2)
->$call_m('baz', 3),
);
Also possible with maybe not existing hash or array references:
... = try_chain { $any->foo->[0]->bar(@params)->{key}->baz };
Or better step by step?
... = $any
->$call_m('foo')
->$fetch_i(0)
->$call_m(bar => @params)
->$fetch_k('key')
->$call_m('baz');
Full Try::Tiny support:
... = try_chain { ... } catch { ... } finally { ... };
Solution for the autovivification problem
Switch off possible autovivication:
$result = try_chain {
no autovivification;
$any->foo->{key}->bar(@params)->[0]->baz;
};
@result = try_chain {
no autovivification;
$any->foo->{key}->bar(@params)->[0]->baz;
};
SUBROUTINES/METHODS
sub try_chain
Calls the whole try block, breaks and ignores undef errors.
sub $call_m
Calls the next method if possible.
sub $fetch_i
Calls the next index of an array reference if possible.
sub $fetch_i
Calls the next key of a hash reference if possible.
DIAGNOSTICS
none
CONFIGURATION AND ENVIRONMENT
nothing
DEPENDENCIES
INCOMPATIBILITIES
not known
BUGS AND LIMITATIONS
none
SEE ALSO
AUTHOR
Steffen Winkler
LICENSE AND COPYRIGHT
Copyright (c) 2017, Steffen Winkler <steffenw at cpan.org>
. All rights reserved.
This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself.