Author image Steffen Winkler
and 1 contributors

NAME

Try::Chain - Call method, hash and/or array chains with break on undef

VERSION

0.001

SYNOPSIS

The module exports:

    try       - imported from Try::Tiny
    catch     - imported from Try::Tiny
    finally   - imported from Try::Tiny
    try_chain - implemented in this module
    $call_m   - implemented in this module

Import what needed. The following code describes the full import:

    use Try::Chain qw( try_chain finally try_chain $call_m );

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 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 {
        no autovivication; # optional
        $any->foo->{key}->bar(@params)->[0]->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 in undef.

sub $call_m

Calls the next method. For methods only.

DIAGNOSTICS

none

CONFIGURATION AND ENVIRONMENT

nothing

DEPENDENCIES

parent

Exporter

Try::Tiny

INCOMPATIBILITIES

not known

BUGS AND LIMITATIONS

none

SEE ALSO

Try::Tiny

autovivification

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.