该计划:
use warnings;
use Memoize;
memoize ('F');
sub F{
$n = shift;
return 0 if $n==0;
return 1 if $n ==1;
return F($n-1)+F($n-2);
}
print F(10);
即使是小值,即F(3),F(2)我收到此错误:
Deep recursion on anonymous subroutine at 5.pl line 13.
Out of memory!
答案 0 :(得分:14)
您正在使用的$n
是一个全局包,而不是词法范围到子例程。使用递归实现此(和类似)问题的原因是它们通常使用词法范围的变量编写。这些范围存储在递归展开时所需的状态。如果您的代码没有存储状态,因为您只是反复重复使用相同的变量。如果您在print "$n\n";
之后立即放置shift
,则会看到$n
设置为10,然后是9,8,7,6,5,4,3,2, 1,-1,-2,-3等。递归正在消失。
按如下方式更改您的代码,它将起作用:
use strict;
use warnings;
use Memoize;
memoize('F');
sub F{
my $n = shift; # Notice "my", creating an instance of $n lexically scoped
# to the subroutine. A new instance is tracked for each call.
return 0 if $n == 0;
return 1 if $n == 1;
return F($n-1)+F($n-2);
}
print F(10), "\n";
这将产生55的预期输出。
代码使用这种看似无关紧要的更改(添加my
)的原因是my
创建了一个词法范围的变量,可用于在递归调用的每个级别单独维护状态堆栈,而在使用它时,包全局只有一个状态。