Perl Subroutine Prototype的作用
Perl Subroutine Prototype乍看之下是Perl提供了为Subroutine严格定义输入参数类型的一种途径。我们来看一下它的大致用法:sub only_one_scalar_param($) {
}
only_one_scalar_param 1; #正确
only_one_scalar_param(1); #正确
only_one_scalar_param(1, 2); #编译期间报错
要让Perl Subroutine Prototype能够正常工作,有如下几个条件
[*]subroutine的申明或者定义需要在编译期间可见,通俗点讲就是要在调用之前。
[*]旧的Perl subroutine的调用是在subroutine前加上&,在加上&的情况下,Prototype也不起作用。
#定义在调用之后
only_one_scalar_param(1); #正确
only_one_scalar_param(1, 2); #正确,prototype没起作用
only_one_scalar_param 1; #编译期间报错
sub only_one_scalar_param($) {
}
sub only_one_scalar_param($) {
}
&only_one_scalar_param 1; #正确
&only_one_scalar_param(1); #正确
&only_one_scalar_param(1, 2) #正确,prototype没起作用
那Prototype的到底是用来做什么的呢? 在某些时候,Prototype确实可以用来检验输入参数(如最一开始的例子),并在编译期间就提示错误信息,但是实际上Prototype并不是如通常想象的那样,下面看一个例子
sub only_one_scalar_param($) {
my( $value ) = @_;
print "$value\n";
}
only_one_scalar_param(10); #输出的是10
only_one_scalar_param(qw/1 2 3/); #传入的是个list。 ?!没报错,输出的是3
第一次调用的输出结果很容易让人理解,不过为什么第二次不仅没有错误,而且还输出的是3呢?
因为prototype定义的第一个参数是一个scalar,因此当遇上qw/1 2 3/这个list时,就将其转换成了scalar,即该list的长度。
那Prototype到底有什么用?
1. 省略括号
my @results = myfunc 3, 5;
#相当于 my @results = myfunc(3, 5);
#如果定义了prototype
sub myfunc($);
my @results = myfunc 3, 5;
#相当于 my @results = (myfunc(3), 5);
sub no_param(); #不可以使用参数
2. 编写类似built-in function的函数样式
sub mypush(\@@) {
my( $array_ref, @to_push ) = @_;
push @{$array}, @to_push;
}
mypush @array, 1, 2, 3;
使用Prototype可以让我们写出类似built-in function的subroutine,这是使用prototype的主要目的
perlsub 写道
Because the intent of this feature is primarily to let you define subroutines that work like built-in functions, here are prototypes for some other functions that parse almost exactly like the corresponding built-in.
在其他情况下,使用Prototype是危险的!
再来看一个例子
use List::Util qw( min max );
sub clip_to_range($$@) {
my ($min, $max, @data) = @_;
return map { max( $min, min($max, $_) ) } @data;
}
clip_to_range(1, 2, (5..10));
#min是1, max是2,data是(5..10)
my $range_ref = ; #独立定义了一个range
clip_to_range(@{$range_ref}, (5..10));
#使用这个range, 想表达和上面一次调用相同的意思,但是...
#min是2, max是5,data是(6..10)
为什么min是2呢? 因为@{$range_ref}被当成了第一个scalar参数,被转换成了长度,所以是2。而max则应该是下一个参数,Perl就从(5..10)中把5当做了max,余下的(6..10)就作为data。
程序真正执行的和自己预期的不相同,往往容易导致产生了Bug但是查不出来,因此最好避免这种情况的发生。上面的这个例子正是《Perl Best Practices》中的一条:“Don't use subroutine prototypes.”
页:
[1]