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

Hello folks,

Why would you use the shift function in the following:

my $file = shift || 'foo.html'; open INFILE, '<', $file, or die "$!: can't open $file\n";

Replies are listed 'Best First'.
Re: Shift function and file opening
by shenme (Priest) on Sep 04, 2003 at 12:04 UTC
    To supply a default filename.

    Presumably this is not in a subroutine, so the shift references the @ARGV array containing the arguments from the command line. If there weren't any command line arguments then shift will return 'nothing' using the value undef. The undef value is 'false' so the final value of the logical expression shift || 'foo.html' is the right-hand part, 'foo.html'. Thus if no arguments $file gets set to 'foo.html' as a default value.

      There's a tiny trap here, because not unly undef evaluates to a false value.
      The values that evaluate to false are undef, 0, (), '0' (/me hopes he didn't forget one).
      Try this:
      perl -e "print (shift || 'foo.html');" 0 perl -e "print (shift || 'foo.html');" 1
      daniel.

        You forgot '' (the empty string), which also evaluates to false.

        --
        3dan
Re: Shift function and file opening
by BrowserUk (Patriarch) on Sep 04, 2003 at 12:05 UTC

    The answer to this can be found in perlfunc:shift.

    Shifts the first value of the array off and returns it, shortening the array by 1 and moving everything down. If there are no elements in the array, returns the undefined value. If ARRAY is omitted, shifts the @_ array within the lexical scope of subroutines and formats, and the @ARGV array at file scopes or within the lexical scopes established by the eval '', BEGIN {}, INIT {}, CHECK {}, and END {} constructs.

    What that means is that if your snippet of code is at "file scope", that is to say, not inside a subroutine, then the shift function will operate upon the array @ARGV. In your snippet, it checks to see if a filename was supplied to the program and if it was, then it opens that file. However, if no argument was supplied on the command line, then shift @ARGV will return undef, and the  || 'foo.html'; part of the statement comes into play and $file is set to that, and that is the file that will be opened if it exists. If it doesn't, the the program will die with an error message explaning why.


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
    If I understand your problem, I can solve it! Of course, the same can be said for you.

Re: Shift function and file opening
by bm (Hermit) on Sep 04, 2003 at 12:08 UTC
    my $file = shift || 'foo.html'; is equivalent to:
    my $arg = shift; my $file; if ($arg) { $file = $arg; } else { $file = 'foo.html'; }
    As mentioned, what the shift is doing depends on the context of your snippet in your program. If it appears within a sub block, then it is removing the first element of the argument list. If it is in the main body of your script, then it is removing the first element of @ARGV (which contain the arguments passed to your script from the command line).
    --
    bm
Re: Shift function and file opening
by Abigail-II (Bishop) on Sep 04, 2003 at 12:23 UTC
    It means that $file will become the argument (from either the program, or the current sub routine), and if there isn't an argument, $file becomes foo.html. One could say that foo.html is the default.

    The "and file opening" is a red herring in your title. There's no relationship between the use of shift() and the use of open().

    Abigail

Re: Shift function and file opening
by zby (Vicar) on Sep 04, 2003 at 12:00 UTC
    Tricky indeed! And what is the context? Is it inside a function subroutine? Or is it the whole program?