Perl在计算因子N的递归实现中保持中间结果?

时间:2013-01-01 00:32:13

标签: algorithm perl recursion factorial

在Perl上有一个计算factorial N的递归实现。

sub fact {
  my ($n) = shift;
  return $n if $n <= 2;
  return $n * fact($n - 1);
}

有人可以解释一下Perl在函数给出结果之前保存中间结果的地方吗?

UPD 以及如何使用调试器或使用其他内容来查看它们?

从答案我解释说这个值保存在堆栈中,但我怎么能从堆栈中看到这些值?

4 个答案:

答案 0 :(得分:2)

$n返回的标量存储在堆栈中。

这就是在调用fact之前堆栈的样子:

  • $n在递归级别0中返回的标量
  • 表:
    • $n在递归级别1中返回的标量
    • 表:
      • $n在递归级别2中返回的标量
      • 表:
        • $n-1在递归级别2中返回的标量
        • \&fact在递归级别2中返回的标量

这就是在调用fact之后堆栈的样子:

  • $n在递归级别0中返回的标量
  • 表:
    • $n在递归级别1中返回的标量
    • 表:
      • $n在递归级别2中返回的标量
      • fact($n - 1)在递归级别2中返回的标量

此时,乘法运算符将乘以堆栈上的最后两个值,并将结果放在堆栈上。

  • $n在递归级别0中返回的标量
  • 表:
    • $n在递归级别1中返回的标量
    • 表:
      • $n * fact($n - 1)在递归级别2中返回的标量

然后子回归,

  • $n在递归级别0中返回的标量
  • 表:
    • $n在递归级别1中返回的标量
    • fact($n - 1)在递归级别1中返回的标量

等等。

答案 1 :(得分:2)

使用递归,每次调用中传递的任何参数都会在调用帧/堆栈上进行。使用Carp&amp;咯咯,你可以看到调用帧。当堆栈在到达基本情况时展开($ v == 1)时计算中间结果。它只能在CPU寄存器中吗?运算符(*)将此中间结果与堆栈上的$ v相乘。结帐this article

#!/usr/bin/env  perl

use strict;
use IO::Handle;
use Carp qw(cluck);

STDOUT->autoflush(1);
STDERR->autoflush(1);

sub factorial {
    my $v = shift;

    dummy_func();
    return 1 if $v == 1;
    print "Variable v value: $v and it's address:", \$v, "\ncurrent sub factorial addr:", \&factorial, "\n","-"x40;
    return $v * factorial($v - 1);
}

sub dummy_func {
    cluck;
}

factorial(5);

同样在调试模式下运行会有所帮助。

  

perl -d factorial.pl

答案 2 :(得分:1)

任何调用的中间结果都保存在堆栈中,就像函数中的局部变量一样。

return $n * fact($n - 1);

等同于:

my $temp = fact($n - 1);
return $n * $temp;

更新:我发现您在退货之前也对产品的位置感兴趣。这也是一个临时的堆栈,所以它相当于:

my $temp1 = fact($n - 1);
my $temp2 = $n * $temp1;
return $temp2;

答案 3 :(得分:1)

由于$n被声明为my $n,因此它是一个词法范围的变量,存储在堆栈中,而不是存储在系统表中。有关详细信息,请参阅Perl Variables via my()