6

另请参阅:文档中的什么地方说,虽然测试 readdir 的定义?. (不是重复的;只是密切相关。


许多人将下面的循环视为惯用的:

while (defined(my $file = readdir($dir)) {
    ...
}

代替:

while (my $file = readdir($dir)) {
    ...
}

因为如果文件名只是“0”(零),它应该终止循环,而当没有更多文件时它返回“undef”。

然而,在过去的某个时候,这个测试defined()不再是必要的——似乎有特殊情况的代码允许后一个版本无论如何都可以工作。

我想知道这是如何工作的?

奇怪的是,如果我将调用替换为readdir()调用foo()

sub foo
{
    my ($dir) = @_;
    return readdir($dir);
}

while (my $file = foo($dir)) {
    ...
}

然后代码按照我的预期进行,并在找到名为“0”的文件时终止循环。

(在 MacOS X 10.5.6 上使用 Perl 5.8.9 测试)

4

1 回答 1

12

这是魔术。特别是魔法(记录在perlsyn, perlop,可能还有其他我不记得的地方)。Perl 允许您使用某些速记符号。如果你想看看 Perl 在你背后做什么,你可以使用B::Deparse. 这是一个使用速记循环的文件:

#!/usr/bin/perl

use strict;
use warnings;

opendir my $dir, "/tmp" or die "$!";

while (my $file = readdir($dir)) {
    print "$file\n";
}

如果你运行perl -MO=Deparse filename.pl你会得到 Perl 看到的代码:

use warnings;
use strict 'refs';
die "$!" unless opendir my $dir, '/tmp';
while (defined(my $file = readdir $dir)) {
    do {
        print "$file\n"
    };
}
filename.pl syntax OK
于 2009-05-09T16:54:46.480 回答