这个子程序传递一个文件句柄数组来关闭,它使用foreach
循环逐个关闭:
sub closef
{
foreach(@_) {
my $fh = shift;
close $fh;
}
}
在哪里可以修改这个简单的子程序以使其更好?
我应该使用close shift
而不是两行吗?
答案 0 :(得分:12)
最简洁的方法是使用词法文件句柄,当它们超出范围时自动关闭:
sub firstline {
open( my $in, shift ) && return scalar <$in>;
# no close() required
}
见perldoc perlopentut。
答案 1 :(得分:8)
sub closef { close $_ for @_ }
但是close
函数确实有一个返回值,你通常会检查它。因此,
sub closef { map { close $_ } @_ }
答案 2 :(得分:7)
foreach(@_) {
close $_;
}
或
foreach my $fh (@_) {
close $fh;
}
或
close $_ foreach (@_);
答案 3 :(得分:4)
您的代码没有按照您的想法行事。你说你想要关闭传递给例程的每个文件句柄,但是你只关闭其中一些文件句柄。请考虑以下示例:
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'));
答案 4 :(得分:4)
最初发布的子程序存在问题。
shift
函数需要一个数组作为参数。 foreach
中的隐式变量是标量。
这意味着$fh
仍然未初始化。它可能被忽视的原因是因为(as eugene y points out)词法文件句柄在超出范围时会自行关闭。
顺便说一下,use warnings;
会通知这些事情。
更惯用的方法是使用while
循环:
sub closef {
while ( my $fh = shift @_ ) {
close $fh;
}
}
对于更紧凑的表示法,可以采用for
循环:
sub closef { close for @_; }
与while
循环的等价物不太可读:
sub closef { close while $_ = shift }
shift
修改了被迭代的数组,这使得它不安全。事实上,这是 问题。
答案 5 :(得分:2)
或者你也可以使用map:
map { close $_ } @_;
使用地图,如果你想处理它,你甚至可以获得所有近场通话结果的数组。
my @results = map { close $_ } @_;