Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Reassigning $_ in loop doesn't stick

by bennymack (Pilgrim)
on Jan 21, 2009 at 20:52 UTC ( [id://737946]=perlquestion: print w/replies, xml ) Need Help??

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

Hello, all

I was just bitten by some odd behavior so I decided I'd post it here and see if it's a bug, a gotcha, or a "Why are you doing that? Stop doing that!"

#!/usr/bin/env perl use strict; use warnings; my $aref = [ 'a' .. 'c' ]; warn 'ORIGINAL: $aref = ', join( q(, ), @{ $aref } ); for my $letter ( eval{ @{ $aref } } ) { $letter = 'z' . $letter; } warn 'NOT CHANGED: $aref = ', join( q(, ), @{ $aref } ); for my $letter ( @{ $aref } ) { $letter = 'z' . $letter; } warn 'CHANGED: $aref = ', join( q(, ), @{ $aref } );

What is happening or what it seems is happening is that when I loop through the elements of an array ref that was dereferenced inside of a block eval the assignment to the loop variable doesn't stick. I'm making no judgements one way or the other I'm just wondering what everyone else thinks of this. Thank you.

Replies are listed 'Best First'.
Re: Reassigning $_ in loop doesn't stick
by Limbic~Region (Chancellor) on Jan 21, 2009 at 20:58 UTC
    bennymack,
    See eval.

    In both forms, the value returned is the value of the last expression evaluated inside the mini-program; a return statement may be also used, just as with subroutines.

    Would you think this was weird behavior if your code looked like?:

    for (foo()) { # ... } sub foo { return @{ $aref }; }

    Cheers - L~R

Re: Reassigning $_ in loop doesn't stick
by kyle (Abbot) on Jan 21, 2009 at 21:01 UTC

    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.

      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

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://737946]
Approved by Limbic~Region
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (4)
As of 2024-04-25 18:52 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found