Как результат «0» от readdir () не ложь за некоторое время?

StackOverflow https://stackoverflow.com/questions/843430

Вопрос

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

Это было полезно?

Решение

Это магия. В частности, когда волшебство (задокументировано в 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 Вы получаете код, который видит:

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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top