I was hunting a weird bug for a very long time and at last found the evil insect in my colleague's code. This instantly drove me totally mad:
# drop first two arguments map shift(@ARGV),[0,1];
I think, some people should be arrested when trying to use map, or even better, prohibited using anything but Java.

P.S. (spoiler) It actually drops only one argument as [0,1] is a list of only one element (which is an arrayref) not two, as one could think.

Replies are listed 'Best First'.
Re: map() abuse or child with a chainsaw
by demerphq (Chancellor) on May 13, 2002 at 14:15 UTC
    Im assuming that your "arrested" comment only applies to "some people". I use map all the time. And when its used right it makes code clearer not the opposite. The above is just a joke as it really says
    shift @ARGV;
    My guess is that it should have said
    # drop first two arguments map shift(@ARGV),(0,1);
    And your colleague got confused. Which really isnt anything to do with map.

    Yves / DeMerphq
    ---
    Writing a good benchmark isnt as easy as it might look.

      If I think of future readers of my code I'll write:
      map shift(@ARGV), qw(two times);
      ...or (best of all)...
      shift(@ARGV); shift(@ARGV);

      But this guy I wrote about, should only be allowed to use straight foreach loops from now on :=E (I'm a little emotive right now, excuse me). At least he won't be able to abuse arrayref constructor for plain old parens.

        Just for sheer TIMTOWTDI:
        @ARGV = @ARGV[2..$#ARGV]; # or for the paran paranoid: @ARGV = (@ARGV)[(2..$#ARGV)];
        ... but i don't like copying the ARGV array back to itself. More readable might be:
        my $discard1 = shift; my $discard2 = shift;
        Out of curiosity, why would one even want to discard the first two arguments like that anyway? Seems like a bad idea in the first place.

        Hmmmm ... sounds like time to pull out one of the Getopt modules to me. ;)

        jeffa

        L-LL-L--L-LL-L--L-LL-L--
        -R--R-RR-R--R-RR-R--R-RR
        B--B--B--B--B--B--B--B--
        H---H---H---H---H---H---
        (the triplet paradiddle with high-hat)
        
        map shift(@ARGV), qw(two times)
        Well, no dont do that.

        :-)

        A very good hint is that you are using map in void context. Thats dumb. (no offense to obfuscators at large ;-). Map is _meant_ to return a set of values, its not meant to be used as a for loop. (In fact my personal belief is that map() and grep() are sorely sorely misnamed. They should be called apply() and filter(), but thats another flame-war iykwim)

        I would say that your second choice is preferred, or possibly

        shift @argv for (1,2);
        But map in void context? No thanks.

        Oh and of course, using Getopt would be a good idea too. (jeffa++)

        Yves / DeMerphq
        ---
        Writing a good benchmark isnt as easy as it might look.

Re: map() abuse or child with a chainsaw
by particle (Vicar) on May 13, 2002 at 14:44 UTC
    if i were removing values from @ARGV, i'd make it very clear. splice makes the intent obvious, as does an assignment to undef. additionally, it avoids the bad practice of using map in void context.

    # drop first two arguments of @ARGV (undef, undef) = splice @ARGV, 0, 2;
    oh, and if the coder mistakenly typed [undef, undef] = ..., it generates a compile-time error -- no need to rely on warnings and strict.

    ~Particle *accelerates*

Re: map() abuse or child with a chainsaw
by rinceWind (Monsignor) on May 13, 2002 at 14:33 UTC
    Not sure that this shouldn't be called shift abuse rather than map abuse, or possibly anonymous arrayref confusion. Consider the equally egregious
    shift(@ARGV) foreach ([0,1]);
    However, the two sorts of brackets does give it a more unnatural feel.

    This is an example of confusing anonymous arrayrefs with lists, which IMO belongs in the list of traps for the unwary. I have seen several examples of Perl newbie code which has made this mistake, and it is on my checklist of things to look out for when helping people spot bugs.

Re: map() abuse or child with a chainsaw
by perrin (Chancellor) on May 13, 2002 at 17:08 UTC
    I've also seen many abuses of map. If you see someone using things like map frequently, it's usually a sign that the person doesn't really have a good grasp on Perl and is trying to apply one solution to every prolem.

    This might be a clearer way to do it:

    # ignore first two args my (undef, undef, $foo, $bar, $baz) = @_;
    A hash of named parameters would be even better.