http://qs321.pair.com?node_id=817300


in reply to push foreach glob - bug?

When you have a problem, don't hide the errors! Use use strict; and use warnings;.

$ perl -Mstrict -wle'my @f = glob("*.mp3"); push @{$f[/ad/]}, $_ forea +ch @f;' Can't use string ("bar.mp3") as an ARRAY ref while "strict refs" in us +e at -e line 1.

In the first snippet, $f[0] and $f[1] contain undef or an array reference. push @{$f[...]}, pushes unto the referenced array (creating it if necessary).

In the second snippet, $f[0] and $f[1] contain file names. push @{$f[...]}, uses the file name as an array name and push unto the named array.

$ perl -le '@f = glob("*.mp3"); push @{$f[/ad/]}, $_ foreach @f; use D +ata::Dumper; print Dumper(\@f, \@{"bad.mp3"}, \@{"bar.mp3"})' $VAR1 = [ 'bad.mp3', 'bar.mp3', 'foo.mp3', 'moo.mp3' ]; $VAR2 = [ 'bar.mp3', 'foo.mp3', 'moo.mp3' ]; $VAR3 = [ 'bad.mp3' ];

Perhaps you shouldn't use the same array to save your file names and your arrays of file names...

Replies are listed 'Best First'.
Re^2: push foreach glob - bug?
by sfink (Deacon) on Jan 14, 2010 at 01:05 UTC
    Doh! I'm an idiot. Thanks. I had turned on warnings, but not strict. Surprisingly, warnings showed nothing -- I was expecting to get something from using the return value of /ad/ as an array index when /ad/ failed to match.

    But yes, I somehow completely missed the fact that I was using the same array for both purposes. I think my subconscious was thinking that because I was using array refs, I was using $f not @f. Stupid subconscious.

    Another case of being blinded by thinking it was too simple for such an obvious problem to hide...

      I was expecting to get something from using the return value of /ad/ as an array index

      You got lucky.

      On failure, when called in scalar context, it happens to return a value that's both the number zero and the empty string.

      On success, when called in scalar context, it happens to return 1.

      Both results are undocumented and unreliable. You're only guaranteed to get a true or false value.

      $f[ /.../ ]
      should be
      $f[ /.../ ? 1 : 0 ]