Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?

list slice

by eXile (Priest)
on Jul 21, 2006 at 18:21 UTC ( #562911=perlquestion: print w/replies, xml ) Need Help??

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

I'd like to know the year (in localtime) a file was last modified. I know I can do that with:
my @stat = stat($file); my @localtime = localtime($stat[9]); my $year = $localtime[5] + 1900;
I was wondering if there was a readable shorter version of writing for this. the only thing that I can come up with is:
my $year = localtime((stat($file))[9])[5] + 1900;
but that doesn't work. I've explained this to myself as 'stat' and 'localtime' return lists and not arrays, so you can't use that kind of syntax. Anybody know of a shorter readable way to produce the same result?

PS: I wouldn't mind seeing a golfing-type shorter version :)

Replies are listed 'Best First'.
Re: list slice
by bart (Canon) on Jul 21, 2006 at 18:25 UTC
    You were so close. This works:
    my $year = (localtime((stat($file))[9]))[5] + 1900;

    The basic idea is that to take an indexed item from the result of a function that returns a list, is to wrap the function call in extra parens. Like this:

    my $sixth = (foo(@args))[5];

    Alternatively, you can wrap it in an anonymous array, too:

    my $sixth = [foo(@args)]->[5];
    The arrow is not optional.

    So, this will work, too:

    my $year = [localtime([stat($file)]->[9])]->[5] + 1900;
Re: list slice
by ikegami (Pope) on Jul 21, 2006 at 18:40 UTC

    By going down this path, you are preventing yourself from checking if stat returned an error.

      This is not a path I recommend; it may fail for time travelers:
      my $year = ( ( localtime( ( (stat("."))[9] || die "stat die" ) ) )[5] || die "localtime die" ) + 1900;
      Be well,
Re: list slice
by ysth (Canon) on Jul 21, 2006 at 19:05 UTC
    List slices have the form ( LIST ) [ LIST ], where both the brackets and parens are part of the syntax.

    But I second ikegami's comment.

Re: list slice
by imp (Priest) on Jul 21, 2006 at 22:50 UTC
    I've found that keeping your code as simple and easy to read as possible is generally the best policy. It makes maintenance and debugging easier, and is kinder to people who inherit your project.

    Additionally, the simplistic code generally runs faster than the "clever" methods.

    That said, have fun with abusing the language to satisfy curiosity :)

    I recently wrote this as an experiment in getting localtime in yyyy-mm-dd format without declaring any local variables, and satifying strict.

Re: list slice (fewer)
by tye (Sage) on Jul 21, 2006 at 22:35 UTC

    There is also a way to make it work without quite so many parens:

    my $year= ( localtime (stat $file)[9] )[5] + 1900;
    my $year= ( localtime +(stat $file)[9] )[5] + 1900;

    There are several cases where the more traditional func( args... ) can be "improved" to ( func args... ). But it won't work if func() isn't known to Perl at the time that this code is compiled.

    Update: Have I mentioned recently that I hate the "looks like a function call" rule. Not allowing func (...) was a good feature that should've stayed and will be restored with Perl6. (:

    - tye        

Re: list slice
by jwkrahn (Monsignor) on Jul 21, 2006 at 21:52 UTC
    If you want to do it all on one line then:
    my ( $year ) = localtime( ( stat $file )[ 9 ] ) =~ /(\d{4})/;

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://562911]
Approved by bart
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others meditating upon the Monastery: (3)
As of 2020-09-27 13:23 GMT
Find Nodes?
    Voting Booth?
    If at first I donít succeed, I Ö

    Results (142 votes). Check out past polls.