http://www.perlmonks.org?node_id=257464

mvaline has asked for the wisdom of the Perl Monks concerning the following question:

As I mentioned in Passing subroutines as arguments, I'm working through SICP and trying to apply what I'm learning to Perl.

SICP contrasts iterative vs recursive processes and the importance of not confusing this with iterative vs recursive procedures. Whereas the term "recursive procedure" refers merely to the syntactic fact that a procedure definition refers to the procedure itself, when we describe a processes as recursive or iterative, we are talking about how the process evolves, not how it is written.

SICP also says that the distinction between process and procedure can be confusing today because most implementation of common languages (including C) are designed in such a way that the interpretation of any recursive procedure consumes an amount of memory that grows with the number of procedure calls, even when the process described is, in principle, iterative. As a consequence, these languages can describe iterative processes only by resorting to special-purpose looping constructs. LISP, of course, does not share this defect and will execute an iterative process in constant space, even if the iterative processes is described by a recursive procedure. Languages with this property are called "tail-recursive."

I've translated the examples in SICP into Perl: a theoretically recursive and iterative way to compute factorials. When Perl executes these subroutines, is there any difference between them? Is Perl tail-recursive?

#!/usr/bin/perl -w use strict; my $result = factorial_recursive(5); print "factorial_recursive(5) returns $result\n"; $result = factorial_iterative(5); print "factorial_iterative(5) returns $result\n"; sub factorial_recursive() { my $n = shift; if ($n == 1) { return(1); } else { return($n * &factorial_recursive(($n - 1))); } } sub factorial_iterative() { my $n = shift; return(fi_helper(1, 1, $n)); } sub fi_helper() { my ($product, $counter, $max_count) = @_; if ($counter > $max_count) { return($product); } else { return(fi_helper(($counter * $product), ($counter + 1), $max_count +)); } }