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

The following snippet of perl code behaves in a manner that I do not understand. I realize there is another approach but I want to learn what perl is doing in this snippet (The entire test program is at the end of the post) :
foreach $ralias (@{$refarrayptr}) { $raliashash = $ralias; $reference = $ref{$raliashash}; $ralias = ${$reference}[0]; }
$refarrayptr is a reference to an array containing hash keys. $ref is a reference to a hash containing references to anonymous arrays. Using the x command in the perl debugger, $refarrayptr looks as follows:
DB<43> x $refarrayptr 0 ARRAY(0x9bfef4c) 0 'key' DB<44>
Once $ralias has been reassigned with the value of the first element of the $reference array, $ralias doesn't have the value of the first element and the first element of $refarrayptr changes from 'key' to the first element of the $reference array as seen below once again in the debug output:
DB<48> x $refarrayptr 0 ARRAY(0x9bfef4c) 0 'a' DB<49>
Here is the output of the code:
./testprob.pl Initial content of ARRAY(0x9ead350) -> key Final content of ARRAY(0x9ead350) -> a
$ralias is a simple scalar (I think). Why is the assignment to $ralias changing the $refarrayptr array since it is a simple scalar. Thank you
#!/usr/bin/perl @list = qw(a b c d); $reflist = \@list; #$ref{$reflist} = $reflist; $ref{'key'} = $reflist; push(@refarray,keys %ref); $refarrayptr = \@refarray; foreach $ralias (@{$refarrayptr}) { print "Initial content of $refarrayptr -> " . @{$refarrayptr}[0] . + "\n"; $raliashash = $ralias; $reference = $ref{$raliashash}; $ralias = ${$reference}[0]; print "Final content of $refarrayptr -> " . @{$refarrayptr}[0] . " +\n"; }

Replies are listed 'Best First'.
Re: assignment to scalar changing array content
by sgifford (Prior) on Nov 16, 2005 at 05:18 UTC
    Inside foreach loops, the iterator variable is actually an alias for the element in the array, and if you change it it will change the contents of the array. From perlsyn(1):

    Foreach Loops

    If any element of LIST is an lvalue, you can modify it by modifying VAR inside the loop. Conversely, if any element of LIST is NOT an lvalue, any attempt to modify that element will fail. In other words, the "foreach" loop index variable is an implicit alias for each item in the list that you're looping over.

    You can work around this by just copying the loop variable into a normal scalar variable:

    foreach $loop_ralias (@{$refarrayptr}) { my $ralias = $loop_ralias; # ... }
Re: assignment to scalar changing array content
by ysth (Canon) on Nov 16, 2005 at 07:01 UTC
    $reference = $ref{$raliashash}; $ralias = ${$reference}[0]; }
    $refarrayptr is a reference to an array containing hash keys. $ref is a reference to a hash containing references to anonymous arrays.
    Then you'd want $ref->{$raliashash} there.
      This syntax can also be applied to the second line.
      $ralias = ${$reference}[0]; # is the same as ... $ralias = $reference->[0];
      I find the second style much easier to read.
      ---
      my name's not Keith, and I'm not reasonable.