Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
有没有更简洁的方法用Perl编写?_Perl_File - Fatal编程技术网

有没有更简洁的方法用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 }