有没有更简洁的方法用Perl编写?
此子例程被传递一个要关闭的文件句柄数组,它使用有没有更简洁的方法用Perl编写?,perl,file,Perl,File,此子例程被传递一个要关闭的文件句柄数组,它使用foreach循环逐个关闭该数组: sub closef { foreach(@_) { my $fh = shift; close $fh; } } sub closef { while ( my $fh = shift @_ ) { close $fh; } } 在哪里可以修改这个简单的子例程以使其更好 我应该使用close shift而不是两行操作吗 f
foreach
循环逐个关闭该数组:
sub closef
{
foreach(@_) {
my $fh = shift;
close $fh;
}
}
sub closef {
while ( my $fh = shift @_ ) {
close $fh;
}
}
在哪里可以修改这个简单的子例程以使其更好
我应该使用close shift
而不是两行操作吗
foreach(@_) {
close $_;
}
或
或
但是close
函数确实有一个返回值,您通常最好检查它。所以,
sub closef { map { close $_ } @_ }
最简洁的方法是使用词法文件句柄,当它们超出范围时会自动关闭:
sub firstline {
open( my $in, shift ) && return scalar <$in>;
# no close() required
}
子第一行{
打开(我的$in、shift)和返回标量;
#不需要关闭()
}
请参阅perldoc.或您也可以使用地图:
map { close $_ } @_;
使用map,如果您想处理关闭调用的所有结果,您甚至可以获得一个数组
my @results = map { close $_ } @_;
您的代码没有按您的想法执行。您说要关闭传递给例程的每个文件句柄,但只关闭其中的一部分。考虑下面的例子:
sub t{
foreach(@_){
my $tmp = shift;
print $tmp;
}
}
t(('a'...'d'));
这将输出
ab
尽管参数列表是a、b、c和d。这是因为在每次迭代中都会调用移位。以获得您想要使用的行为
sub t{
foreach(@_){
my $tmp = $_;
print $tmp;
}
}
t(('a'...'d'));
或者,更好的做法是,不要复制$\的副本,只需将其别名为:
sub t{
foreach my $tmp (@_){
print $tmp;
}
}
t(('a'...'d'));
最初发布的子程序有问题 函数需要一个数组作为参数。
foreach
中的隐式变量是标量
这意味着,$fh
保持未初始化状态。它可能不被注意的原因是()词法文件句柄在超出范围时会自动关闭
顺便说一句,使用警告
将通知此类事件
更惯用的方法是使用while
循环:
sub closef
{
foreach(@_) {
my $fh = shift;
close $fh;
}
}
sub closef {
while ( my $fh = shift @_ ) {
close $fh;
}
}
对于更紧凑的表示法,可以使用For
循环:
sub closef { close for @_; }
使用while
循环的等效项可读性较差:
sub closef { close while $_ = shift }
更新
迈克尔·卡曼下面的评论在这里是正确的。
shift
修改正在迭代的数组,这使其成为不安全的操作。事实上,这就是问题所在。+1使用词法文件句柄,并在其作用域退出时让它们自行关闭。感谢@eugene,我不知道这些,我们将继续探讨。这不会像您认为的那样。你不可能忘记你正在经历的事情。行为是不可预测的。我支持@tchrist的基本信息。如果要使用shift,while(@)
更适合循环。如果要foreach
,只需关闭$\uu
。或者,请参阅@David Dorward的第二个示例,说明如何将foreach
与变量赋值相结合。如果确实检查了值,您可能还需要检查$代码>变量,虽然这在错误处理方面是一个很大的改进,但这还不够100%。使用shift
时存在问题,但这并不是缺少参数。它将在@
或@ARGV
上运行,具体取决于使用位置;它在这里工作。问题是在foreach
中使用它。来自perlsyn:foreach
如果在循环体中添加或删除元素,将会非常混乱。非常感谢这些示例。我不知道这是怎么回事。
sub closef { close while $_ = shift }