Tib*_*bor 1 error-handling recursion perl function parameter-passing
为什么Perl中的以下递归factorial失败,即使它在C++和Java中有效?
Java的:
public static long factorial(int n) {
if (n == 0) {
return 1;
} else {
return factorial(n-1) * n;
}
}
Run Code Online (Sandbox Code Playgroud)
C++:
long factorial(int n) {
if (n == 0)
return 1;
else
return n * factorial(n-1);
}
Run Code Online (Sandbox Code Playgroud)
但是这个在Perl(use Carp;)中失败了:
sub factorial {
my $n = shift || croak "null value for argument";
return 1 if $n == 0; # base case
return $n * factorial($n-1);
}
Run Code Online (Sandbox Code Playgroud)
错误消息(第10行是调用函数的地方main(),第16行是第二个return语句):
null value for argument at ./fact1.pl line 14.
main::factorial(0) called at ./fact1.pl line 16
main::factorial(1) called at ./fact1.pl line 10
Run Code Online (Sandbox Code Playgroud)
(以下内容已经编辑,感谢Matt Jacob在原版中指出了我的遗漏.)
原始版本,没有鲤鱼,但有|| return,错误信息是:
Use of uninitialized value in multiplication (*) at ./fact1.pl line 16.
Run Code Online (Sandbox Code Playgroud)
这是在没有命令行参数时尝试使脚本保持静默的结果.(没有抱怨uninitialized value.)
对基本案例的一个小修改使它在Perl中也可以工作:
sub factorial {
my $n = shift || croak "null value for argument";
return 1 if $n == 1; # base case
return $n * factorial($n-1);
}
Run Code Online (Sandbox Code Playgroud)
(当然,代价是取消处理0(零)输入.)
得到教训
对于被认为是真实的东西,Perl有一些相当不正统的规则.
特别是,当在布尔表达式中使用时,数字0被认为是假的.所以当你说这个
my $n = shift || croak "null value for argument";
Run Code Online (Sandbox Code Playgroud)
如果shift将0作为参数,则将其视为false,这意味着||运算符需要计算其第二个操作数.
幸运的是,Perl的编写者预见到了这种用例,因此他们定义了一个替代或运算符.而||检查是否所述第一值是truthy,//所述第一值检查是否定义.
my $n = shift // croak "null value for argument";
Run Code Online (Sandbox Code Playgroud)
这将按照您的意图行事,除非有可能$n是字面值undef.在这种情况下,你需要一些更复杂的内省来检查参数是否存在,但是为了这个阶乘函数的目的,这应该足够了.
| 归档时间: |
|
| 查看次数: |
119 次 |
| 最近记录: |