in reply to Reassigning $_ in loop doesn't stick

Ordinarily if you loop over an array, the loop variable becomes an alias to each element of the array. If you're looping over the results of some other expression, however, you can't always map them to some array element, so the loop variable is actually a copy.

Update: This is totally wrong! I really need to try it before I post it!

For example, in this case, we're filtering the elements of the array. Even though the elements of the original array are passed through unaltered, it doesn't alias them.

foreach my $x ( grep defined, @foo ) { $x = rand; ]

Here's an example where the elements get modified (with map) even before reaching the foreach, so the loop variable can't be an alias to the original values.

foreach my $x ( map "x$_", @foo ) { $x = rand; }

Your example with eval is another example where the expression being looped over won't be aliased to the loop variable.

You can find foreach documented in perlsyn.

Replies are listed 'Best First'.
Re^2: Reassigning $_ in loop doesn't stick
by ikegami (Patriarch) on Jan 21, 2009 at 21:09 UTC

    This is totally wrong!

    It's even documented. Just like @array returns its elements as aliases,

    grep returns aliases into the original list

    $ perl -MDevel::Peek -e' my $x; Dump $x; Dump $_ for $x; Dump grep 1, $x; Dump do { $x }; Dump map $_, $x; Dump sub { $x }->(); Dump eval { $x }; ' 2>&1 | grep 'SV =' SV = NULL(0x0) at 0x814ecdc # Address of $x SV = NULL(0x0) at 0x814ecdc # for aliases SV = NULL(0x0) at 0x814ecdc # grep aliases SV = NULL(0x0) at 0x814ecdc # do aliases SV = NULL(0x0) at 0x814ed9c # map copies SV = NULL(0x0) at 0x814f7f8 # sub copies SV = NULL(0x0) at 0x814ed9c # eval copies
      ikegami,
      I sent you a /msg to this affect but since I found a conflict in map, I figured I would post for everyone's benefit. What version of perl is this and why doesn't it agree with the documentation (map aliases not copies)?

      Update: Confirmed with 5.10.0 that map aliases not copies
      I am guessing I am not understanding what you are saying.

      #!/usr/bin/perl use strict; use warnings; my @foo = 'a' .. 'd'; map { $_ = uc($_) } @foo; # look Mom, map in a void context print "@foo\n";

      Cheers - L~R

        Both grep and map operate on aliases in their block, as you show.

        What ikegami is showing is that grep will return aliases to the elements of the list it worked on while map will return copies (even if it hasn't modified them).

        The post to which you replied discusses whether map returns aliases or not. This is not related to whether map operates on an alias when executing the code block.

        What version of perl is this and why doesn't it agree with the documentation

        The docs (for 5.10.0) specify that grep returns aliases, but they are silent on whether map returns aliases or not.

        Confirmed with 5.10.0 that map aliases not copies

        Your snippet discards the return value of map without checking whether it's an alias or not.