<?xml version="1.0" encoding="windows-1252"?>
<node id="162191" title="Re: Re: Re: Pure Perl tail call optimization" created="2002-04-26 02:18:07" updated="2005-08-12 09:29:51">
<type id="11">
note</type>
<author id="96022">
abstracts</author>
<data>
<field name="doctext">
Okay, you say that &lt;tt&gt;goto &amp;SUB&lt;/tt&gt; doesn't create a new stack frame, so let's test it shall we:
&lt;code&gt;
#!/usr/bin/perl -w

my $method = shift or usage();
if($method eq 'tail'){
    $0 = 'tail';
    tail_inf();
} elsif($method eq 'nontail'){
    $0 = 'nontail';
    nontail_inf();
} else {
    usage();
}

sub tail_inf{
    L1: print_resources(); goto L2;
    L2: goto L1;
}

sub nontail_inf{
    goto &amp;T1;
    sub T1{ print_resources(); goto &amp;T2; }
    sub T2{ goto &amp;T1; }
}

{
    my $i=0;
    my $j=0;
    sub print_resources{
        $i++;
        $i = $i % 100000;
        return unless $i == 0;
        my @lines = grep {$_ =~ /\s+(\d+)/ and $1 eq $$}  `ps u`;
        print @lines;
        $j++;
        exit if $j == 10;
    }
}

sub usage{
    print "Usage: $0 tail|nontail\n";
    exit(-1);
}
&lt;/code&gt;
Run the code twice, one with tail as an arg, and one with nontail, here is what I get on Perl 5.6.1:
&lt;code&gt;
[334]: ./tail.pl tail
abstract  5843  0.0  0.2  2324 1052 pts/0    S    01:00   0:00 tail
abstract  5843 99.9  0.2  2328 1100 pts/0    S    01:00   0:01 tail
abstract  5843 99.9  0.2  2328 1100 pts/0    S    01:00   0:01 tail
abstract  5843 99.9  0.2  2328 1100 pts/0    S    01:00   0:02 tail
abstract  5843 83.6  0.2  2328 1100 pts/0    S    01:00   0:02 tail
abstract  5843 99.9  0.2  2328 1100 pts/0    S    01:00   0:03 tail
abstract  5843 88.0  0.2  2328 1100 pts/0    S    01:00   0:03 tail
abstract  5843 99.9  0.2  2328 1100 pts/0    S    01:00   0:04 tail
abstract  5843 90.6  0.2  2328 1100 pts/0    S    01:00   0:04 tail
abstract  5843 83.8  0.2  2328 1100 pts/0    S    01:00   0:05 tail
[335]: ./tail.pl nontail
abstract  5854 86.0  0.9  6300 5040 pts/0    S    01:00   0:00 nontail
abstract  5854 85.5  1.7 10276 9056 pts/0    S    01:00   0:01 nontail
abstract  5854 85.3  2.5 14244 13024 pts/0   S    01:00   0:02 nontail
abstract  5854 85.7  3.3 18212 16996 pts/0   S    01:00   0:03 nontail
abstract  5854 86.0  4.0 22184 20964 pts/0   S    01:00   0:04 nontail
abstract  5854 85.8  4.8 26148 24928 pts/0   S    01:00   0:05 nontail
abstract  5854 85.8  5.6 30116 28900 pts/0   S    01:00   0:06 nontail
abstract  5854 85.7  6.3 34084 32868 pts/0   S    01:00   0:06 nontail
abstract  5854 85.7  7.1 38056 36836 pts/0   S    01:00   0:07 nontail
abstract  5854 85.9  7.9 42024 40808 pts/0   S    01:00   0:08 nontail
&lt;/code&gt;
Clearly, the nontail calls (&lt;tt&gt;goto &amp;SUB&lt;/tt&gt;) creates new stack frames while the &lt;tt&gt;goto LABEL&lt;/tt&gt; doesn't.
&lt;p&gt;
So, to &lt;i&gt;*correctly*&lt;/i&gt; implement tail calls, I think &lt;tt&gt;goto &amp;SUB&lt;/tt&gt; is improper.
&lt;p&gt;
As for speed, and carrying this example, one can see that the tail call is faster than the nontail call:
&lt;code&gt;
[340]: time ./tail.pl tail &gt; /dev/null
real	0m6.079s
user	0m5.450s
sys	0m0.620s
[341]: time ./tail.pl nontail &gt; /dev/null
real	0m10.423s
user	0m9.530s
sys	0m0.890s
&lt;/code&gt;
However, in this example we have two functions calling each other, so perl might not optimize that.
&lt;p&gt;
As for using computed values for goto (ie &lt;tt&gt;goto "label value"&lt;/tt&gt;, you can do a jump table.  Basically, you have a segment of the code that looks something like this:
&lt;code&gt;
SCM_BRANCH:
  if($br eq 'SCM_F1'){
    goto SCM_F1;
  } elsif ($br eq 'SCM_F2'){
    goto SCM_F2;
  } 
  ... 
SCM_F1:
  # before doing a call, set $rv to where you wanna go
  # and pass the name of where you want to return as first arg
  # ie: call F2 with args $a,$b;
  @_ = ('RET1', $a, $b);
  $br = 'SCM_F2';
  goto SCM_BRANCH; # here we go
RET1: # here we return
  my @returned_vals = @_;
  ...
  $br = $rp;
  goto SCM_BRANCH;
&lt;/code&gt;

&lt;p&gt;
&lt;b&gt;Update:&lt;/b&gt; I agree with [samtregar] that the reason might not be a creation of a new stack frame.  I don't know if this is by design or a bug.  However, &lt;tt&gt;goto LABEL&lt;/tt&gt; does not leak: it can run forever juggeling from label to another and *can* be used to create proper tail recursion.
</field>
<field name="root_node">
161611</field>
<field name="parent_node">
162181</field>
</data>
</node>
