Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is "0" result from readdir() not false in a while condition?

See also: Where in the documentation does it say that while tests readdir for definedness?. (Not a duplicate; just closely related.)


Many people treat the loop below as idiomatic:

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

instead of:

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

because supposedly with the latter version if the filename is just "0" (zero) it should terminate the loop, whereas it returns 'undef' when there are no more files.

However at some point in the past this test for defined() stopped being necessary - there appears to be special case code that allows the latter version to work regardless.

I'd like to know how this works?

Curiously,if I replace the call to readdir() with a call to foo() instead:

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

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

then the code does do what I'd expect, and terminate the loop when a file named "0" is found.

(tested with Perl 5.8.9 on MacOS X 10.5.6)

like image 891
Alnitak Avatar asked May 09 '09 14:05

Alnitak


1 Answers

It is magic. Specifically while magic (documented in perlsyn, perlop, and probably other places I don't remember). Perl allows you certain shorthand notations. If you want to see what Perl is doing behind your back you can use B::Deparse. Here is a file that uses the shorthand loop:

#!/usr/bin/perl

use strict;
use warnings;

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

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

If you run perl -MO=Deparse filename.pl you get the code Perl sees:

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
like image 132
Chas. Owens Avatar answered Sep 19 '22 03:09

Chas. Owens