Como o resultado “0” do readdir () não é falso em um tempo?
-
20-08-2019 - |
Pergunta
Veja também: Onde na documentação diz que, enquanto testam o ReadDir para definição?. (Não é uma duplicata; Apenas intimamente relacionado.)
Muitas pessoas tratam o loop abaixo como idiomático:
while (defined(my $file = readdir($dir)) {
...
}
ao invés de:
while (my $file = readdir($dir)) {
...
}
Porque supostamente com a última versão se o nome do arquivo for apenas "0" (zero), ele deve encerrar o loop, enquanto retorna 'undef' quando não há mais arquivos.
No entanto, em algum momento do passado, este teste para defined()
Pararam de ser necessário - parece haver um código de caso especial que permite que a última versão funcione independentemente.
Eu gostaria de saber como isso funciona?
Curiosamente, se eu substituir a chamada para readdir()
com uma chamada para foo()
em vez de:
sub foo
{
my ($dir) = @_;
return readdir($dir);
}
while (my $file = foo($dir)) {
...
}
então o código faz Faça o que eu esperaria e encerrar o loop quando um arquivo chamado "0" for encontrado.
(Testado com Perl 5.8.9 no macOS x 10.5.6)
Solução
Isto é mágica. Especificamente enquanto mágica (documentada em perlsyn
, perlop
, e provavelmente outros lugares que não me lembro). Perl permite que certas notações abreviadas. Se você quiser ver o que Perl está fazendo nas costas, você pode usar B::Deparse
. Aqui está um arquivo que usa o loop abreviado:
#!/usr/bin/perl
use strict;
use warnings;
opendir my $dir, "/tmp" or die "$!";
while (my $file = readdir($dir)) {
print "$file\n";
}
Se você correr perl -MO=Deparse filename.pl
Você obtém o código Perl vê:
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