Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where in the documentation does it say that while tests readdir for definedness?

Tags:

perl

perldoc

See also: How is "0" result from readdir not false in a while condition?. (Not a duplicate; just closely related.)


Where in the documentation does it say that while tests readdir for definedness? For instance, this code

#!/usr/bin/perl

use strict;
use warnings;

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

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

when run through B::Deparse yields:

use warnings;
use strict 'refs';
die "$!" unless opendir my $dir, '/tmp';
while (defined(my $file = readdir $dir)) {
    do {
        print "$file\n"
    };
}
z.pl syntax OK

I expect this behaviour, but I cannot find where it is specified. In the I/O Operators section of perlop it says

The following lines are equivalent:

     while (defined($_ = <STDIN>)) { print; }
     while ($_ = <STDIN>) { print; }
     while (<STDIN>) { print; }
     for (;<STDIN>;) { print; }
     print while defined($_ = <STDIN>);
     print while ($_ = <STDIN>);
     print while <STDIN>;

But there is no mention of readdir.

like image 640
Chas. Owens Avatar asked May 10 '09 03:05

Chas. Owens


2 Answers

You're quite right about it being undocumented. I've looked rather hard, and I can't find any reference to it being special either. It is special, as you've discovered, and as demonstrated by:

$ perl -MO=Deparse \
       -E'opendir(my $dir, "."); while($_ = readdir($dir)) { say; }'

BEGIN {
    $^H{'feature_say'} = q(1);
    $^H{'feature_state'} = q(1);
    $^H{'feature_switch'} = q(1);
}
opendir my $dir, '.';
while (defined($_ = readdir $dir)) {
    say $_;
}
-e syntax OK

Looking through the source, Perl_newWHILEOP in op.c specifically has tests for readdir, glob, readline and each... Hmm, let's do some digging, and see when readdir was added.

A bit of digging with git reveals that it's been that way since at least 1998, with Gurusamy Sarathy making the relevant change in commit 55d729e4. While I haven't gone digging to see which releases that's gone into, I'd wager it would be at least 5.6.0 and above. I can't find any mention of it in the deltas.

It might be mentioned in the third edition camel book, but I haven't checked to find out.

I think that a patch here (or even just a note to p5p) would certainly be appreciated.

Paul

like image 121
pjf Avatar answered Oct 06 '22 14:10

pjf


I'm sorry that I didn't think to update the pages that you expected to find this information.

I did add a note to the readdir section of perlfunc though.

As of Perl 5.12 you can use a bare readdir in a while loop, which will set $_ on every iteration.

opendir(my $dh, $some_dir) || die;
while(readdir $dh) {
    print "$some_dir/$_\n";
}
closedir $dh;

It doesn't explicitly say that it checks for definedness though.

( I would like to note that adding this feature was my first patch to the Perl core. )

like image 33
Brad Gilbert Avatar answered Oct 06 '22 13:10

Brad Gilbert