Search code examples
perlchaining

How to detect that the method is in the middle of the call chain in Perl?


I have an example object with calc method:

package A;
sub new {...}
sub calc {
    my ($self, $a, $b) = @_;
    return {first => $a, second => $b, sum => $a + $b}
}

And simple usage:

my $result = A->new->calc(1, 2);
print 'Result is ', $result->{sum}; # output: Result is 3

Now, i want to add a chaining method log so that it outputs the parameters of calculation and returns result:

package A;
...
sub calc {
    ...
    return $self->{result} = {...}
}
sub log {
    my $self = shift;
    print sprintf 'a = %d, b = %d', $self->{result}->{first}, $self->{result}->{second};
    return $self->{result};
}

And use it like this cases:

my $result = A->new->calc(10, 20);
print "Result of calc: ", $result->{sum}; # output: 30

$result = A->new->calc(11, 12)->log; # output: a = 11, b = 12
print 'Result is ', $result->{sum}; # output: Result is 23

I tried to use helper object with overloads, but my calc can return very different structures like scalar, array, arrayref, hashref... So, my helper's object code was awful and buggy.

Now, i have two questions:

  1. Can i determine that the method is in the middle of the call chain, rather than the end? Then i could return $self from calc instead of result.
  2. Has it more elegant solution?

Solution

  • So you want the calc method to return a hashref, except when it's called like:

    $object->calc(...)->some_other_method;
    

    ... in which case it needs to return $object itself?

    My first thought is that this absolutely stinks as an API.

    My second thought is that you should be able to accomplish this with Want. But my sense of good taste prevents me from providing a code sample.