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

As much as I hate being one of 'those' guys, I feel the code speaks for itself :P

#!/usr/bin/perl -w use strict; my ($sec, $min, $hour) = (localtime)[0..2]; print "$hour:$min:$sec\n"; ($sec, $min, $hour) = localtime[0..2]; print "$hour:$min:$sec\n"; __END__ 22:9:50 9:16:24

The former print statement displayed the correct time while the latter (obviously) did not. Why?

Update (30 min after initial post): Thanks for the explanations (and the pleonastic code correction).

I'm so adjective, I verb nouns!

chomp; # nom nom nom

Replies are listed 'Best First'.
Re: (localtime) versus localtime - round 1
by ikegami (Patriarch) on Sep 28, 2008 at 02:38 UTC
    localtime[0..2] means localtime([0..2])

    You are constructing an array with three elements, getting a reference to it and passing it to localtime. localtime treats the reference as a number, resulting in the address, and uses the address as the number of seconds since epoch.

    use POSIX qw( strftime ); my $ref = [ 0 .. 2 ]; print($ref, "\n"); printf("%X\n", 0+$ref); print(strftime('%Y-%m-%d %H:%M:%S', localtime($ref)), "\n"); print(strftime('%Y-%m-%d %H:%M:%S', localtime(0+$ref)), "\n");
    ARRAY(0x225248) 225248 1970-01-26 19:48:08 1970-01-26 19:48:08

    The parentheses are necessary to remove the ambiguity (by requiring an operator instead of an expression).

    perl -MO=Deparse and perl -MO=Deparse,-p help with parsing problems.

    Update: Corrected spelling mistake pointed by jwkrahn.

      parenthesis are

      Should be either parenthesis is or parentheses are.

      You have nine pairs of parentheses in your example.   Which ones are you using to remove the ambiguity?

        ah thanks. And none. I was explaining why the OP's second snippet worked.
Re: (localtime) versus localtime - round 1
by jwkrahn (Abbot) on Sep 28, 2008 at 02:43 UTC

    localtime returns a list and  ( )[0..2] is a list slice that narrows down that list to the first three elements.   localtime also accepts a numerical argument (usually time) but the number you are supplying in the second example is a reference to an anonymous array (localtime[0..2] is the same as localtime\@array).  But as you are reading from the beginning of the list you don't really need the list slice at all:

    my ($sec, $min, $hour) = localtime;

    Will do the same as the first example.

Re: [Updated] (localtime) versus localtime - round 1
by Fletch (Bishop) on Sep 28, 2008 at 05:59 UTC

    And as usual when "strange" parsing behaviors rear their head, B::Deparse knows all . . .

    BEGIN { $^W = 1; } use strict 'refs'; (my($sec, $min, $hour) = (localtime)[(0..2)]); print(((((($hour . ':') . $min) . ':') . $sec) . "\n")); (($sec, $min, $hour) = localtime([(0..2)])); print(((((($hour . ':') . $min) . ':') . $sec) . "\n")); __DATA__

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.