Как результат "0" из readdir() не ложен в состоянии while?

См. Также: Где в документации говорится, что во время тестирования 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".

(протестировано с Perl 5.8.9 на MacOS X 10.5.6)

1 ответ

Решение

Это волшебство Конкретно пока магия (задокументировано в 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
Другие вопросы по тегам