以下代码
#!/usr/bin/env perl
use strict;
use warnings;
my @foo = (0,1,2,3,4);
foreach my $i (@foo) {
sub printer {
my $blah = shift @_;
print "$blah-$i\n";
}
printer("test");
}
不符合我的期望。
到底是什么情况?
(我希望它可以打印出“test-0\ntest-1\ntest-2\ntest-3\ntest-4\n”)
最佳答案
问题在于,不能像sub name {...}
循环中那样嵌套for
构造。
原因是因为sub name {...}
实际上意味着BEGIN {*name = sub {...}}
和begin块在解析后就立即执行。因此,子例程的编译和变量绑定(bind)发生在编译时,而for循环才有机会运行。
您要做的是创建一个匿名子例程,该例程将在运行时绑定(bind)其变量:
#!/usr/bin/env perl
use strict;
use warnings;
my @foo = (0,1,2,3,4);
foreach my $i (@foo) {
my $printer = sub {
my $blah = shift @_;
print "$blah-$i\n";
};
$printer->("test");
}
哪个打印
test-0
test-1
test-2
test-3
test-4
大概在您的实际用例中,这些闭包将被加载到数组或哈希中,以便以后可以访问。
您仍然可以在闭包中使用裸字标识符,但是您需要做一些额外的工作以确保名称在编译时可见:
BEGIN {
for my $color (qw(red blue green)) {
no strict 'refs';
*$color = sub {"<font color='$color'>@_</font>"}
}
}
print "Throw the ", red 'ball'; # "Throw the <font color='red'>ball</font>"