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

Hello. I'm confused about why map is acting differently with ++ and * :
use 5.016; my @array = 0..5; my @incremented = map { $_++ } @array; say "@array"; # 1 2 3 4 5 6 say "@incremented"; # 0 1 2 3 4 5 my @array = 0..5; my @doubled = map {$_ * 2} @array; say "@array"; # 0 1 2 3 4 5 say "@doubled"; # 0 2 4 6 8 10

Why is @incremented not incremented but @doubled is doubled? And why is @array affected in the first case by manipulating $_ but not the second? I'm reading perldoc -f map to see a reason but I'm not grokking it so far. I know to use foreach to modify the org array if I had to - just wondering why map is acting like this. Thanks for any insight.

Replies are listed 'Best First'.
Re: map confusion
by GrandFather (Saint) on Dec 15, 2015 at 23:48 UTC

    $_++ is a post increment. The value used is the value $_ contained before being incremented. Unless there is a compelling reason to use the post increment operator you should always use the pre increment operator: ++$_.

    Oh, and it's nothing to do with map!

    Premature optimization is the root of all job security

      Thank-you. However even with ++$_, @array is still affected in the first case, but not with *. Any thoughts on why?

        Let's say you have a variable $A and you do this:
        $A = 5; $B = $A++; print $A; # prints out 6. $B is 5
        $A = 5; $B = ++$A; print $A; # prints out 6. $B is 6
        $A = 5; $B = $A*2; print $A; # prints out 5. $B is 10
        $A = 5; $B = $A+1; print $A; # prints out 5. $B is 6


        Because ++ changes the original AFTER the operation, and mutiplication just returns the result, without modifying the original.

Re: map confusion
by Cristoforo (Curate) on Dec 16, 2015 at 00:12 UTC
    As GrandFather said, $_ gets passed to @incremented before its incremented.

    From the docs for map: Note that $_ is an alias to the list value, so it can be used to modify the elements of the LIST. That explains why the original elements in @array change. $_++ modifies the element $_ and $_ * 2 doesn't modify $_.

      Thanks Monks. Got it.