Perl对静态代码检查的支持有限,特别是它可以检查我们是否将适当数量的参数传递给函数。例如,这将导致错误:
use strict;
use warnings;
sub f($) {}
f(2, 3)
Too many arguments for main::f
如果我们过早调用f,我们会收到另一个有用的警告:
use strict;
use warnings;
f(2, 3)
sub f($) {}
main::f() called too early to check prototype
这将导致错误:
use strict;
use warnings;
sub f($) {}
sub g() { f(2, 3) }
Too many arguments for main::f
我的问题是,我们是否可以针对以下情况获取此类消息:
use strict;
use warnings;
sub g() { f(2, 3) }
sub f($) {}
因为我在这里没有收到任何错误或警告。如果我可以阻止编译代码,那将是件好事。请指教。
答案 0 :(得分:11)
“知情人士”(最值得一提的是Damian Conway在他的书“Perl Best Practices”中)建议不要使用子程序原型,因为它们只能通过“使得无法推断出的参数传递行为来混淆代码”。只需查看通话即可调用子程序。“
答案 1 :(得分:2)
是的,您可以在实际使用之前预先声明它:
use strict; use warnings; sub f($); # prototype defined sub g() { f(2, 3) } sub f($) { print "hi\n"; }
答案 2 :(得分:2)
不要使用原型对已经指出的所有无数原因进行参数检查。这样做是有诱惑力的,因为它们提供了编译时检查,但是它们的检查仅限于愚蠢的错误,它们不检查方法调用,并且它们具有意想不到的副作用。
使用Method::Signatures等模块进行实际参数检查,并为您提供参数处理。
use Method::Signatures;
use strict;
use warnings;
func g() { f(2, 3) }
func f($foo) {
print "f got $foo\n";
}
当子程序运行时会发生检查(现在有一个错误,它没有检查你是否传递了太多的参数,修复了)但是它为你提供了更丰富的工具集在没有原型的所有令人讨厌的副作用的情况下检查您的参数(类型即将推出)。它适用于方法调用,原型不适用。