Perl通过原生子程序签名提升级别
虽然Perl 5.20版本预计要到春天才会发布,但现在您已经可以使用最新的Perl开发版本中的子程序签名功能了。
要求
您需要安装最新版本的Perl开发版本(v5.19.9)。您可以使用Perlbrew来获取。
$ perlbrew install perl-5.19.9
$ perlbrew switch perl-5.19.9
或者您可以从cpan.org下载并构建Perl v5.19.9。
一旦安装了5.19.9,您将需要实验性发行版。您可以在命令行使用cpan进行安装。
$ cpan experimental
子程序签名解释
子程序签名是子程序参数的正式列表。您可以像这样声明子程序签名:
use experimental 'signatures';
sub echo ($message) {
print "$message\n";
}
在这个例子中,“($message)”是子程序签名。这表示所有对echo子程序的调用都必须传递一个参数。当调用子程序时,参数将被分配给$message,并在子程序的范围内可用。
默认值
签名还可以为其参数声明默认值。让我们给echo子程序添加一个默认消息:
use experimental 'signatures';
sub echo ($message = 'Hello World!') {
print "$message\n";
}
现在当不带参数调用子程序时,$message的值将默认为“Hello World!”。
子程序签名还可以声明可选的和贪婪的参数。如果您想查看示例,请查看Perl的官方文档中的新子程序签名条目。
参数检查
将签名添加到子程序中可以为该子程序的所有调用启用参数检查。例如,以下代码在运行时将生成错误:
use experimental 'signatures';
sub echo ($message) {
print "$message\n";
}
echo(); # missing argument
$ perl echo.pl
Too few arguments for subroutine at echo.pl line 3.
如果传递了过多的参数,Perl也会引发错误。
use experimental 'signatures';
sub echo ($message) {
print "$message\n";
}
echo('hello', 'world'); # too many arguments
$ perl echo.pl
Too many arguments for subroutine at echo.pl line 3.
这很有帮助,因为它避免了在子程序内部编写样板参数检查代码的需要。但请注意;由于没有值检查,以下代码不会引发参数错误。
use experimental 'signatures';
sub echo ($message) {
print "$message\n";
}
echo(undef); #undef is an argument
更简洁的代码
您可以将那些令人讨厌的变量赋值从子程序中删除。再见(以及永别)吧:
sub ugly_code {
my ($arg1, $arg2, arg3) = @_;
...
}
而欢迎这个:
sub fine_code ($arg1, $arg2, arg3){
...
}
更多增强功能即将到来
与功能齐全的Method::Signatures模块相比,原生子程序签名实现是一个最小化的版本。Perl原生子程序签名的主要赞助商Peter Martini已经确认计划在未来添加类型检查、别名、只读副本和命名参数。他预计这些功能中的每一个都将带来速度上的改进。
重新审视Python和Perl的比较
在《快速Python书,第二版》的第5页(The Quick Python Book, Second Edition)中,作者比较了等效的Perl和Python函数的可读性。在作者看来,Python代码比Perl代码更易读。这是一个稻草人论点,因为Perl示例是使用“婴儿Perl”编写的,但让我们使用Perl的原生子程序签名功能重新审视这个例子。这是未修改的Python示例:
def pairwise_sum(list1, list2):
result = []
for i in range(len(list1)):
result.append(list1[i] + list2[i])
return result
这是原始的Perl代码示例:
sub pairwise_sum {
my($arg1, $arg2) = @_;
my(@result) = ();
@list1 = @$arg1;
@list2 = @$arg2;
for($i=0; $i < length(@list1); $i++) {
push(@result, $list1[$i] + $list2[$i]);
}
return(\@result);
}
这是重构后的Perl版本:
sub pairwise_sum {
my ($arg1, $arg2) = @_;
return map { $arg1->[$_] + $arg2->[$_] } 0 .. $#$arg1;
}
这段代码比原始的Perl代码更简洁、更短。它也比Python示例更短。但是,它是更简洁的吗?使用子程序签名,我们可以做得更好:
sub pairwise_sum ($arg1, $arg2) {
return map { $arg1->[$_] + $arg2->[$_] } 0 .. $#$arg1;
}
您可以看到,使用子程序签名为我们节省了一行参数赋值代码。现在没有争议:Perl代码比Python示例更短、更简洁。太棒了!
结论
子程序签名在技术上对Perl来说是一次飞跃,对Perl社区来说是一次推动。看到显著的语言进步是令人鼓舞的,而且还有更多的发展在路上。有了后缀解引用、新的性能改进以及现在的子程序签名,Perl 5.20 将成为自 5.10 以来最重要的版本。2014 年春天,我们期待着!
2014-02-24:文章更新以纠正错误检查实现、Perl 代码示例并阐明 Peter Martini 在 Perl 内核签名开发中的作用。
喜欢这篇文章吗?帮助一下我们,转发它!
这篇文章最初发布在 PerlTricks.com。
标签
反馈
这篇文章有什么问题吗?通过在 GitHub 上打开一个 issue 或 pull request 来帮助我们。