Search code examples
perlfunctionreturngotocallstack

perl goto&Name vs return


I came accross a piece of perl code recently. The code looks like below

package CODE;

sub _doJob
{
    $result = JOB->new(@_)->doIt();
    return $result;
}

sub _doFirstJob
{
    unshift @_, '1';
    goto &_doJob;
}

sub _doSecondJob
{
    unshift @_, '2';
    goto &_doJob;
}

sub _doThirdJob
{
    unshift @_, '3';
    goto &_doJob;
}

and then calling the functions like

$result = CODE::_doFirstJob($a);
$result = CODE::_doSecondJob($a);
$result = CODE::_doThirdJob($a);

Question is what is the significance of goto here? If I write similar function calls with return, like below, what would be the problem?

package CODE;

sub _doJob
{
    $result = JOB->new(@_)->doIt();
    return $result;
}

sub _doFirstJob
{
    unshift @_, '1';
    return &_doJob(@_);
}

sub _doSecondJob
{
    unshift @_, '2';
    return &_doJob(@_)
}

sub _doThirdJob
{
    unshift @_, '3';
    return &_doJob(@_)
}

I could still call these functions in same way

$result = CODE::_doFirstJob($a);
$result = CODE::_doSecondJob($a);
$result = CODE::_doThirdJob($a);

I know that goto &NAME actually makes perl to exit from current function and replace it with the new function in call stack. But how am I being benefited by this here?


Solution

  • You can save some time and memory by skipping the stack handling. You can use Benchmark to test if the difference is significant in your case.

    Reading about "Tail Call" might also give some information. For example, see this old thread at PerlMonks.

    Update

    I tested with the following script:

    sub rec {
        $_[0]++;
    
        sleep 5, return if $_[0] > 1000;
    
        return rec(@_); # Comment this line.
        goto &rec
    }
    
    rec(1 .. 200);
    

    The time difference isn't measurable, the memory consumption is quite different: the return case takes almost twice as more bytes than the goto one. With higher number of iterations, the memory consumption stays the same for goto, but grows with return.