How do I handle errors in methods chains in Perl?

后端 未结 3 810
谎友^
谎友^ 2021-02-04 12:06

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

3条回答
  •  挽巷
    挽巷 (楼主)
    2021-02-04 12:51

    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;
    

提交回复
热议问题