drc*_*law 2 perl anonymous-function
借用Javascript一词,在perl中IIFE的“最佳实践”方法是什么?
我下面的测试代码是一个简单的循环,它调用匿名子程序并立即执行以构建子程序数组(这仅返回循环索引)。这主要是我想要的,但是我需要使用一个中间变量(而不是使用@_,它会在内部函数上更改)。
use warnings;
use strict;
my @funcs;
for(my $i=0;$i<3;$i++) {
sub {
my $index=shift;
$funcs[$index]=sub {$index};
}
-> ($i);
}
for (@funcs) {
print &$_()."\n";
}
Run Code Online (Sandbox Code Playgroud)
#Output
0
1
2
Run Code Online (Sandbox Code Playgroud)
我知道我可以map用来重组这个问题。但撇开这一点,有没有更好的方法可以做到这一点?
更新资料
感谢@ikegami突出了一些要点。
仅出于对这个问题的未来看法,我对此有以下看法:
“迭代器” for循环的作用域(是否是地图?)与“ c样式” for循环的作用域不同。这样就完全不需要IIFE即可清理代码。甜。
更新2
以下代码显示了我所看到的差异。我并不是说一个比另一个更好,但是很高兴知道。我的输出是0 1 2,但第一个仅重复$ i的最后一个值(++运算符后为3)。
use warnings;
use strict;
my @funcs;
print "C loop direct assignment of sub\n";
for(my $i=0;$i<3;$i++) {
$funcs[$i]= sub {$i};
}
print &$_()."\n" for @funcs;
print "C loop direct assignment of sub with variable\n";
for(my $i=0;$i<3;$i++) {
my $index=$i; #assignment/copy
$funcs[$index]= sub {$index};
}
print &$_()."\n" for @funcs;
print "For loop interator\n";
@funcs=[];
for my $i (0..2) {
$funcs[$i]=sub {$i};
}
print &$_()."\n" for @funcs;
print "C loop with IIFE assignment\n";
@funcs=[];
for (my $i=0;$i<3;$i++) {
sub {
my $index=shift;
$funcs[$index]=sub {$index};
}
-> ($i);
}
print &$_()."\n" for @funcs;
Run Code Online (Sandbox Code Playgroud)
出来的是:
C loop direct assignment of sub
3
3
3
C loop direct assignment of sub with variable
0
1
2
For loop interator
0
1
2
C loop with IIFE assignment
0
1
2
Run Code Online (Sandbox Code Playgroud)
相当于Perl
(function () {
var x = ...;
...
})();
Run Code Online (Sandbox Code Playgroud)
是
sub {
my $x = ...;
...
}->();
Run Code Online (Sandbox Code Playgroud)
就是说,IIFE只是Perl根本不需要的解决方法。
(function () {
var x = ...;
...
})();
Run Code Online (Sandbox Code Playgroud)
是一种解决方法
{
my $x = ...;
...
}
Run Code Online (Sandbox Code Playgroud)
和
var result = (function () {
return ...;
})();
Run Code Online (Sandbox Code Playgroud)
是一种解决方法
my $result = do {
...
};
Run Code Online (Sandbox Code Playgroud)
您似乎正在尝试翻译与以下内容类似的内容:
let funcs = [];
for (let i=0; i<3; ++i) {
(function() {
var index = i;
funcs.push( function() { return index; } );
})();
}
for (let func of funcs)
console.log(func());
Run Code Online (Sandbox Code Playgroud)
以下是直接翻译:
my @funcs;
for (my $i=0; $i<3; ++$i) {
sub {
my $index = $i;
push @funcs, sub { $index };
}->();
}
say $_->() for @funcs;
Run Code Online (Sandbox Code Playgroud)
但是,使用IIFE根本没有意义。只需使用以下内容即可:
my @funcs;
for (my $i=0; $i<3; ++$i) {
my $index = $i;
push @funcs, sub { $index };
}
say $_->() for @funcs;
Run Code Online (Sandbox Code Playgroud)
现在,人们倾向于在Perl中避免使用C样式的for循环,因为使用foreach循环更具可读性(并且更有效!)。这也使解决方案更加简单,因为foreach循环的循环变量的作用域是循环体,而不是循环语句。
my @funcs;
for my $i (0..2) {
push @funcs, sub { $i };
}
say $_->() for @funcs;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
96 次 |
| 最近记录: |