Question

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)

Was it helpful?

Solution

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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top