readdir()的"0"结果如何在一段时间内不是假的?

Aln*_*tak 6 perl while-loop readdir defined

另请参阅:文档中的哪些内容表示测试readdir的定义性?.(不重复;只是密切相关.)


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

while (defined(my $file = readdir($dir)) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

代替:

while (my $file = readdir($dir)) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

因为假设文件名只是"0"(零),所以应该使用后一版本,它应该终止循环,而当没有更多文件时它返回'undef'.

但是在过去的某个时刻,这个测试已经defined()停止了必要 - 似乎有一些特殊的案例代码允许后一个版本无论如何都能工作.

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

奇怪的是,如果我更换调用readdir()与调用foo()来代替:

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

while (my $file = foo($dir)) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

那么代码确实做了我期望的事情,并在找到名为"0"的文件时终止循环.

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

Cha*_*ens 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";
}
Run Code Online (Sandbox Code Playgroud)

如果你运行,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
Run Code Online (Sandbox Code Playgroud)

  • 如果有人可以提供指向特定文档的链接,那么B :: Deparse的+1会非常有用.我无法在man perlsyn中找到它. (3认同)