stat() bug

Discussion in 'Perl Misc' started by ssojoodi@gmail.com, Oct 27, 2005.

  1. Guest

    Hello,

    While debugging a Perl script, I came across a statement like this:

    my @myarray = ("str1", "str2", "str3", "str4");
    my $foo = (stat(@myarray))[2];
    print $foo;

    [result]: str3

    I know that this is not the proper usage of the stat function, but I'm
    wondering why this script works! I could not find documentation on
    this within the perlfunc manual, so I figured this may be a bug.

    Any ideas?

    Regards,
    Sahand
    , Oct 27, 2005
    #1
    1. Advertising

  2. Paul Lalli Guest

    wrote:
    > While debugging a Perl script, I came across a statement like this:
    >
    > my @myarray = ("str1", "str2", "str3", "str4");
    > my $foo = (stat(@myarray))[2];
    > print $foo;
    >
    > [result]: str3
    >
    > I know that this is not the proper usage of the stat function, but I'm
    > wondering why this script works! I could not find documentation on
    > this within the perlfunc manual, so I figured this may be a bug.
    >
    > Any ideas?


    Running the above code through -MO=Deparse shows us:
    my(@myarray) = ('str1', 'str2', 'str3', 'str4');
    my $foo = (stat @myarray)[2];
    print $foo;

    >From that, you can see that '@myarray' is not being passed as an

    argument to stat, but rather that array is being expanded so that the
    expression is really saying:
    (stat 'str1', 'str2', 'str3', 'str4')[2]

    stat is defined as a unary operator, so `stat 'str1'` binds more
    tightly than does the comma operator. Therefore, the list that's
    created above is the list containing: (return_val_of_stat('str1'),
    'str2', 'str3', 'str4')

    Since the entire operation is being done in scalar context (that is,
    you are assigning to the scalar variable $foo, the stat() call is also
    done in scalar context, so it simply returns a true or false value, as
    defined by the relevant perldoc.

    You are then taking the third element of that list, which is 'str3'.

    (Please note that I am mildly confused as to why @myarray isn't forced
    into scalar context by the stat call, rather than expanded into a list,
    but this does explain the results that are created)

    Paul Lalli
    Paul Lalli, Oct 27, 2005
    #2
    1. Advertising

  3. Guest

    wrote:
    > my @myarray = ("str1", "str2", "str3", "str4");
    > my $foo = (stat(@myarray))[2];
    > print $foo;
    > [result]: str3
    >
    > I know that this is not the proper usage of the stat function, but I'm
    > wondering why this script works!


    I'm not sure if you could call it a 'bug' because, as you say, it's not
    the proper use of the function.

    But it does seem it ought to throw at least a warning. Interestingly
    enough:

    #!/usr/bin/perl
    use strict; use warnings;
    my @myarray = ("str1", "str2", "str3", "str4");
    print stat @myarray;
    __END__

    [output:]str1str2str3

    (notice the array has been pop()ped).
    , Oct 27, 2005
    #3
  4. Anno Siegel Guest

    <> wrote in comp.lang.perl.misc:
    > Hello,
    >
    > While debugging a Perl script, I came across a statement like this:
    >
    > my @myarray = ("str1", "str2", "str3", "str4");
    > my $foo = (stat(@myarray))[2];
    > print $foo;
    >
    > [result]: str3
    >
    > I know that this is not the proper usage of the stat function, but I'm
    > wondering why this script works! I could not find documentation on
    > this within the perlfunc manual, so I figured this may be a bug.
    >
    > Any ideas?


    What's happening is rather bizarre, especially when you play around
    with

    my @myarray = qw( str0 str1 str2 str3 str4);
    my @foo = stat( @myarray[1 .. 4]);
    print "@foo\n";

    However, since the documentation doesn't say what stat() does when called
    with more than one argument, it is rather a case of "Don't do that, then".
    I guess bailing out with an error message would be better behavior, but
    I'm not filing a bug because of this.

    I wouldn't trust a program that uses this construct. What were they
    thinking stat() was doing?

    Anno
    --
    If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers.
    Anno Siegel, Oct 27, 2005
    #4
  5. Paul Lalli Guest

    wrote:
    > wrote:
    > > my @myarray = ("str1", "str2", "str3", "str4");
    > > my $foo = (stat(@myarray))[2];
    > > print $foo;
    > > [result]: str3
    > >
    > > I know that this is not the proper usage of the stat function, but I'm
    > > wondering why this script works!

    >
    > I'm not sure if you could call it a 'bug' because, as you say, it's not
    > the proper use of the function.
    >
    > But it does seem it ought to throw at least a warning. Interestingly
    > enough:
    >
    > #!/usr/bin/perl
    > use strict; use warnings;
    > my @myarray = ("str1", "str2", "str3", "str4");
    > print stat @myarray;
    > __END__
    >
    > [output:]str1str2str3
    >
    > (notice the array has been pop()ped).


    Not really. The array isn't being changed at all. (examine the
    contents of @myarray after the print to verify). What seems to be
    happening is that stat is invoking a scalar context on the list
    contained in @myarray. Accordingly, the first three values are
    evaluated and thrown away, and the fourth value is actually passed to
    stat(). Since no such file named 'str4' actually exists on your
    system, that stat call returns an empty list. The print then prints
    the first through third values as is, followed by the return value of
    stat('str4').

    You can verify this by replacing these dummy strings with names of
    actual files:

    $ touch file1.txt
    $ touch file2.txt
    $ touch file3.txt
    $ touch file4.txt
    $ perl -Mstrict -w -MData::Dumper
    my @files = qw/file1.txt file2.txt file3.txt file4.txt/;
    my @results = stat(@files);
    print Dumper(\@results);
    __END__
    $VAR1 = [
    'file1.txt',
    'file2.txt',
    'file3.txt',
    51987534,
    591538,
    33204,
    1,
    5111,
    50,
    0,
    '0',
    1130434354,
    1130434354,
    1130434354,
    8192,
    0
    ];


    All very bizarre, regardless.

    Paul Lalli
    Paul Lalli, Oct 27, 2005
    #5
  6. Paul Lalli <> wrote:
    > wrote:
    >> While debugging a Perl script, I came across a statement like this:
    >>
    >> my @myarray = ("str1", "str2", "str3", "str4");
    >> my $foo = (stat(@myarray))[2];
    >> print $foo;
    >>
    >> [result]: str3
    >>
    >> I know that this is not the proper usage of the stat function, but I'm
    >> wondering why this script works! I could not find documentation on
    >> this within the perlfunc manual, so I figured this may be a bug.
    >>
    >> Any ideas?

    >
    > Running the above code through -MO=Deparse shows us:
    > my(@myarray) = ('str1', 'str2', 'str3', 'str4');
    > my $foo = (stat @myarray)[2];
    > print $foo;
    >
    >>From that, you can see that '@myarray' is not being passed as an

    > argument to stat, but rather that array is being expanded so that the
    > expression is really saying:
    > (stat 'str1', 'str2', 'str3', 'str4')[2]
    >
    > stat is defined as a unary operator, so `stat 'str1'` binds more
    > tightly than does the comma operator. Therefore, the list that's
    > created above is the list containing: (return_val_of_stat('str1'),
    > 'str2', 'str3', 'str4')
    >
    > Since the entire operation is being done in scalar context (that is,
    > you are assigning to the scalar variable $foo, the stat() call is also
    > done in scalar context,



    The stat call is in *list* context (it is part of a list slice).

    The list slice, in turn, is what is in scalar context.


    > so it simply returns a true or false value, as
    > defined by the relevant perldoc.
    >
    > You are then taking the third element of that list, which is 'str3'.
    >
    > (Please note that I am mildly confused as to why @myarray isn't forced
    > into scalar context by the stat call,



    Me too.


    > rather than expanded into a list,
    > but this does explain the results that are created)



    --
    Tad McClellan SGML consulting
    Perl programming
    Fort Worth, Texas
    Tad McClellan, Oct 27, 2005
    #6
  7. Guest

    Paul, your example provides a good idea of what stat() does. The scalar
    context of a list is usually either the count of the number of elements
    in the list or the last item of the list.

    So the stat call stat(@files) becomes:

    [ 'file1.txt', 'file2.txt', 'file3.txt', stat($file[4]) ]

    The right thing to to do is to probably discard file1.txt, file2.txt
    and file3.txt completely. Also, if file4.txt could not be found, I
    would imagine $! or $@ to be set, instead of returning an empty list.

    -SN
    , Oct 27, 2005
    #7
  8. Also sprach Tad McClellan:
    > Paul Lalli <> wrote:


    >> (Please note that I am mildly confused as to why @myarray isn't forced
    >> into scalar context by the stat call,

    >
    >
    > Me too.


    This looks like a bug to me. CORE::stat has a prototype of '*' which -
    when given an array - should yield the array length. This is at least
    what happens with user functions having that prototype.

    Tassilo
    --
    use bigint;
    $n=71423350343770280161397026330337371139054411854220053437565440;
    $m=-8,;;$_=$n&(0xff)<<$m,,$_>>=$m,,print+chr,,while(($m+=8)<=200);
    Tassilo v. Parseval, Oct 28, 2005
    #8
  9. Joe Smith Guest

    wrote:
    > stat($file[4])
    > Also, if file4.txt could not be found, I
    > would imagine $! or $@ to be set, instead of returning an empty list.


    Definitely not $@ since eval() is not being used.
    You should expect $! to be set _AND_ an empty list.
    -Joe
    Joe Smith, Oct 31, 2005
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Steven T. Hatton
    Replies:
    3
    Views:
    9,705
    Pete Becker
    Jun 2, 2005
  2. Patrick Useldinger

    os.stat('<filename>')[stat.ST_INO] on Windows

    Patrick Useldinger, Feb 27, 2005, in forum: Python
    Replies:
    6
    Views:
    1,169
    =?ISO-8859-1?Q?=22Martin_v=2E_L=F6wis=22?=
    Mar 3, 2005
  3. Magesh
    Replies:
    3
    Views:
    444
    Gordon Burditt
    Oct 5, 2007
  4. Rolf Krüger
    Replies:
    2
    Views:
    613
    Ian Collins
    Mar 12, 2008
  5. ruck
    Replies:
    10
    Views:
    1,273
Loading...

Share This Page