我只是好奇为什么在Perl中选择使用匿名子例程,而不是命名的子例程。谢谢。
解决方法
>您可以在数组,哈希和标量中存储匿名子程序。
>您可以在运行时构建它们
>您可以将它们作为参数传递给其他函数。
你可以把变量保存在周围的范围内。
>您可以在运行时构建它们
>您可以将它们作为参数传递给其他函数。
你可以把变量保存在周围的范围内。
最后一点可能是最重要的,因为它通常是Perl中命名与匿名子程序最突出的一个方面。例:
sub outer { my $a = 123; sub inner { print $a,"\n"; } # At this point,$a is 123,so this call should always print 123,right? inner(); $a = 456; } outer(); # prints 123 outer(); # prints 456! Surprise!
但是将“内部”从一个命名的子程序改为对一个匿名子程序的引用,它的工作原理就不那么令人惊讶:
sub outer { my $a = 123; my $inner = sub { print $a,"\n"; }; # At this point,and since the anonymous subrotine # whose reference is stored in $inner closes over $a in the # "expected" way... $inner->(); $a = 456; } # ...we see the "expected" results outer(); # prints 123 outer(); # prints 123
(当然,每个人的期望是不同的,因此“预期”周围的“惊吓报价”)
以下是实际代码中的一个示例(尽管应该注意的是,File :: Find界面通常被认为是一个糟糕的代码 – 由于它使用全局变量,而不是使用匿名子例程):
sub find_files { my @files; my $wanted = sub { if($something) { push @files,$File::Find::name; } }; # The find() function called here is imported from File::Find find({ wanted => $wanted },$directory); return @files; }
传递一个命名子程序作为所需参数的值将需要使用只能使用一次的例程来污染命名空间,并且在find_files()子例程中定义一个命名子例程将会呈现前面所展示的“意外”行为。