Perl List Slice Weirdness

A colleague at work just found this little gem in File::Copy::Recursive:

  my $two = join '-', ( stat $cur )[0,1] || '';

That should pick out the device and inode, join them with a hyphen and set $two to the empty string if the stat failed. However, there’s a precedence problem:

  # Intended code.
  my $two = join( '-', ( stat $cur )[0,1] ) || '';
  # Actual code.
  my $two = join '-', ( ( stat $cur )[0,1] ) || '';

Spot the difference? The || bit applies to the result of the list slice. But what happens when you use || on a list slice? Let’s look at the debugger…

    DB<1> x @statinfo = stat '/etc/hosts'
  0  2050
  1  327794
  2  33188
  3  1
  4  0
  5  0
  6  0
  7  332
  8  1089379886
  9  1134738486
  10  1134738486
  11  4096
  12  8
    DB<2> x @statinfo[0,1]
  0  2050
  1  327794
    DB<3> x @statinfo[0,1] || ''
  0  327794
    DB<4> x @statinfo[0,1,2] || ''
  0  33188

So it appears that putting a list slice into scalar context always returns the last element of the list. Weird. More info (including examples at perldoc/C-style Logical Or).

Hopefully, he’ll file a bug report as it was actually tripping him up…

Update: RT#19205

Comments 2

  1. Aristotle Pagaltzis wrote:

    You are surprised about that? I’d expect any seasoned Perl 5 programmer to know that neither @a = @b || @c nor @a = ( 1, 2 ) || ( 3, 4 ); DWIMs – what you have is just an instance of this. That you generated the list using a slice is a red herring.

    Maybe you need to re-read Japhy’s famous “List” is a Four-Letter Word article? 🙂

    I doubt this will be changed in Perl 5… it’s fixed in Perl 6, though.

    One more point: the || '' bit is dead code.

    $ perl -le'print defined join "-", ()'
    1
    

    join always returns a string – when you join nothing, it returns an empty string, not undef.

    Posted 11 May 2006 at 16:45
  2. Dominic Mitchell wrote:

    I did know that lists don’t work like that at all; I was just surprised by the combination of the list slice. I’m just pleased to say that it wasn’t in my code. 🙂

    OTOH, I’m always glad that I can learn more about the language, so many years after starting.

    Posted 11 May 2006 at 21:02