有没有更简洁的方法在Perl中写这个?

时间:2010-10-29 08:04:14

标签: perl file

这个子程序传递一个文件句柄数组来关闭,它使用foreach循环逐个关闭:

sub closef
{
    foreach(@_) {
        my $fh = shift;
        close $fh;
    }   
}

在哪里可以修改这个简单的子程序以使其更好?

我应该使用close shift而不是两行吗?

6 个答案:

答案 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 $_ } @_;