In Perl, the foreach loop allows convenient iteration over array elements, where the loop variable by default ($_, or explicitly specified) references the array element rather than copying its value.
Example:
my @arr = (1, 2, 3); foreach my $x (@arr) { $x *= 2; } # @arr is (2, 4, 6) — elements have been modified!
To get a copy of the value (and not a reference to the original element), you need to explicitly assign it:
foreach my $x ( @arr ) { # $x is a reference to the element ... } # ↓↓↓↓ foreach (@arr) { my $copy = $_; ... } # $copy is a copy, $_ is a reference to the element
You should not use the same variable in multiple nested foreach loops, otherwise, you can encounter unexpected side effects.
Is the variable in the foreach loop an independent copy, and can it be safely modified within the loop body?
The usual answer is: "Yes, because the loop itself creates the variable — you can change it however you like."
Correct Answer:
In Perl, the loop variable by default (e.g., foreach $var (@arr)) is an alias (reference) to the array element. Any modification to the loop variable results in changing the original element!
To modify a temporary copy — do an explicit assignment within the loop:
foreach my $elem (@arr) { my $t = $elem; $t++; # only a copy, the original array does not change }
History
History 1
In a record filtering task, a programmer modified their loop variable, unaware that they were changing the original data. Subsequent calculations were based on the modified array, resulting in an incorrect sum of the elements. The error only became evident when compared to a reference sample.
History 2
A nested foreach loop used the same variable ($item). The inner loop variable overwrote the state of the outer one, causing results from the first pass to be lost, and some elements of the array ended up with incorrect values.
History 3
An array of references to hashes was iterated through foreach, and in each loop, the loop variable was assigned a new value. As a result, the references were "broken" — scalars were stored instead of reference values, and the next processing stage failed with a type error.