我一直对perl中匿名subs的用途和用法感到困惑.我理解这个概念,但是寻找这个实践的价值的例子和解释.
要明确:
sub foo { ... } # <--- named sub sub { ... } # <--- anonymous sub
例如:
$perl -e 'print sub { 1 }' CODE(0xa4ab6c)
告诉我,sub返回一个标量值.所以我可以做:
$perl -e '$a = sub { 1 }; print $a'
与上述相同的输出.这当然适用于所有标量值,因此您可以使用匿名subs来加载数组或散列.
问题是,如何使用这些subs?为什么要使用它们?
而对于一个金星,有没有任何问题,只能用匿名子解决?
解决方法
匿名子程序可用于各种事物.
>事件处理系统的回调:
my $obj = Some::Obj->new; $obj->on_event(sub {...});
迭代器
sub stream {my $args = \@_; sub {shift @$args}} my $s = stream 1,2,3; say $s->(); # 1 say $s->(); # 2
>高阶功能:
sub apply (&@) { my $code = shift; $code->() for my @ret = @_; @ret } my @clean = apply {s/\W+/_/g} 'some string','another string.'; say $clean[0]; # 'some_string'
>创建别名数组:
my $alias = sub {\@_}->(my $x,my $y); $alias[0]++; $alias[1] = 5; say "$x $y"; # '1 5''
>使用闭包进行动态编程(例如创建只有少量差异的一组子例程):
for my $name (qw(list of names)) { no strict 'refs'; *$name = sub {... something_with($name) ...}; }
没有一个匿名子程序可以做任何命名子程序不能执行的情况.我的$ref = sub {…}构造函数等同于以下内容:
sub throw_away_name {...} my $ref = \&throw_away_name;
而不必为每个子项决定唯一的“throw_away_name”.
等价也是相反的,子名称{…}等同于:
BEGIN {*name = sub {...}}
要调用子程序引用,可以使用以下任一项:
$code->(); # calls with no args $code->(1,3); # calls with args (1,3) &$code(); # calls with no args &$code; # calls with whatever @_ currently is
my $list = sub {@{ $_[0] }}; say for [1 .. 10]->$list # which prints 1 .. 10