ajt has asked for the wisdom of the Perl Monks concerning the following question:

While idly reading the Camel (3rd edition) I noticed on page 99 that if you do a stat or file test on a file, then you can do more tests on the same file using _ as Perl caches the initial file test - thus reducing the number of system calls Perl has to make.

Thus you can do:

if (-e $file && -T _) { print "foo"; }
instead of the more obvious, though slower:
if (-e $file && -T $file) { print "bar"; }

I was quite inpressed with this, indeed it's mentioned again in chapter 24. I tried some tests this morning, and using the underscore is quite a bit faster on my Wintel box, than separate tests.

I've never seen this construct before, though it's easy enough to miss, and even though I've seen it now it's hard to search for an underscrore like this, as underscore is used in some many other places.

Q1 Does anybody actually use this construct? I don't recall seeing it in any books, though I've just this minute found it in the excellent Effective Perl Programming

Q2 What other little tricks like this have I missed? I know there are many things I must have missed, so this question is like asking how long is a piece of string, but what are peoples favourite coding constructs that are "cool" but uncommon

As ever, thanks in advance...

Replies are listed 'Best First'.
Re: Does anyone use underscore pseudo-filehandle?
by rob_au (Abbot) on Sep 30, 2001 at 16:51 UTC
    I found this method of referencing in the HTML::Template module as I was reading through the module source this evening. It was used in quite an interesting manner in the _mtime subroutine which checks for the existence of the requested template file and then obtains the system modification timestamp for the file through stat - This modification timestamp is used in HTML::Template in conjunction with its caching functions. The code from HTML::Template is as follows:

    sub _mtime { my ($self, $filepath) = @_; my $options = $self->{options}; return(undef) if ($options->{blind_cache}); # make sure it still exists in the filesystem (-r $filepath) or Carp::confess("HTML::Template : template file $f +ilepath does not exist or is unreadable."); # get the modification time return (stat(_))[9]; }

    As you can see, the _ construct is passed to stat following the -r (readable) test on the file, presumably given that this stat information is also cached in a similar manner to file test information.

     

    Update

    Following through on this at perlfunc:_X, it appears that these file tests obtain the information required to return a positive or negative test result via a system stat call. From perlfunc:_X ...

    If any of the file tests (or either the stat() or lstat() operators) are given the special filehandle consisting of a solitary underline, then the stat structure of the previous file test (or stat operator) is used, saving a system call. (This doesn't work with -t, and you need to remember that lstat() and -l will leave values in the stat structure for the symbolic link, not the real file.)

    print "Can do.\n" if -r $a || -w _ || -x _; stat($filename); print "Readable\n" if -r _; print "Writable\n" if -w _; print "Executable\n" if -x _; print "Setuid\n" if -u _; print "Setgid\n" if -g _; print "Sticky\n" if -k _; print "Text\n" if -T _; print "Binary\n" if -B _;

     

    Ooohhh, Rob no beer function well without!

Re: Does anyone use underscore pseudo-filehandle?
by merlyn (Sage) on Sep 30, 2001 at 19:00 UTC
    The underscore pseudo-filehandle was described in llama 1 and llama 2, although we've dropped it for llama 3 as being not as important as covering "use strict" a bit better.

    The underscore pseudo-filehandle is actually one of the very few features that I can claim is entirely my own idea. I suggested to Larry during the Perl3 alpha testing phase that performing a separate stat operation for each component of -r $foo && -w $foo was wasteful and subject to phase errors. He came up with the underscore cache in response.

    The other ideas I can claim directly are the list-slice, and the arrow syntax for dereferencing coderefs (introduced on a bet, but that's another story).

    -- Randal L. Schwartz, Perl hacker

Re: Does anyone use underscore pseudo-filehandle?
by demerphq (Chancellor) on Sep 30, 2001 at 18:35 UTC
    Well, besides the _ construct you might want to have a look at the File::stat module. I prefer it for situations like you describe. If only because if a non perl guru needs to maintain the code it'll be a lot easier to track down the appropriate documentation.

    Other tricks? Hmm, well getting the hang of $" $, $\ $/ $; is worth your time, as well as learning the use and flexibility of perls command line options is also cool, I recommend having a look -l and -i as they are pretty useful for small scripts (thanks to various people, merlyn wog for pointing these out). Also for smaller scripts I have developed a fondness for using 1 argumnet opens as I mention here Re: auto-vivifying file handles. While it may not count as tricks, there is lots of stuff to know about perls extended regex syntax, watch for japhy posts as he seems to be an expert.

    Anyways, one of the things that I like about perl is that whenever you think that you've learned all the perl tricks there are to learn some guru comes along and shows you five more that you never heard of....

    :-)

    Yves
    --
    You are not ready to use symrefs unless you already know why they are bad. -- tadmc (CLPM)

Re: Does anyone use underscore pseudo-filehandle?
by blakem (Monsignor) on Sep 30, 2001 at 16:55 UTC
    A1. Yes, that perl idiom is regularly used and highly recommended by those in the know.

    A2. I'll leave that one as an open question, though much perl wisdom is hidden under this link. ;-)

    -Blake

Re: Does anyone use underscore pseudo-filehandle?
by Rudif (Hermit) on Oct 01, 2001 at 02:49 UTC
    Please be careful on Win32. I found out that testing for -T _ and -x _ may give erroneous result, depending on the order of tests. I believe this to be a bug in the Win32 Perl.

    Here is a simple script to illustrate the problem:

    #! perl -w use strict; my $file = 'test.bat'; print "1. $file is a text file, executable\n" if -T $file && -x _; print "2. $file is an executable text file\n" if -x $file && -T _;
    Create a simple file named test.bat and run above script. It prints only this - not what I would expect
    2. test.bat is an executable text file
    See also this node and the replies: Problem with filetest -x _ on Win2k AS Perl build 626.

    Rudif