foreachの制御変数は一時変数ではない

my @array = (1, 2, 3, 4, 5);

foreach my $elm (@array) {
    $elm++;
}

use Data::Dumper;
print Dumper @array;

出力結果は何だろうか?
$elmをPHPのforeachにおけるasの後の変数と同様、一時変数だと思い込んでしまうと、
$elmをインクリメントしても@array本体には影響を与えない、と思ってしまう。
@arrayを書き換えたければ、改めてリファレンス操作なり、別の変数に入れておいて最後に元の変数に移し替えるしかないのだと、思い込んでしまう。
ところがPERLのこの構文の出力結果は、

$VAR1 = 2;
$VAR2 = 3;
$VAR3 = 4;
$VAR4 = 5;
$VAR5 = 6;

こうである。制御変数に対する操作は、元の配列の値を不可逆的に変えてしまうのである。


以前、ハッシュのあるキーを軸にマージを行うコードを書いた。
http://d.hatena.ne.jp/Kow/20180728/1532745189

my %person1 = (
    user_id   => 1234,
    name      => 'test'
);
my %person2 = (
    user_id   => 5678,
    name      => 'hoge'
);
my %person3 = (
    user_id   => 9101,
    name      => 'fuga'
);
my %person4 = (
    user_id => 2345,
    name    => 'aaaa'
);
my @person_list = ();
push(@person_list, \%person1);
push(@person_list, \%person2);
push(@person_list, \%person3);
push(@person_list, \%person4);

my %users1 = (
    id   => 2345,
    note => 'abc',
);
my %users2 = (
    id   => 9101,
    note => 'def',
);
my @user_list = ();
push(@user_list, \%users1);
push(@user_list, \%users2);

my %id_list = map {$_->{id}, $_} @user_list;

my @found_list;
my @not_found_list;

foreach my $person (@person_list) {
    if ($id_list{$person->{user_id}}) {
        $person->{note} = $id_list{$person->{user_id}}->{note};
        push(@found_list, $person);
    } else {
        push(@not_found_list, $person);
    }
}

@person_list = [\@found_list, \@not_found_list];

だがこの、

foreach my $person (@person_list) {
    if ($id_list{$person->{user_id}}) {
        $person->{note} = $id_list{$person->{user_id}}->{note};
        push(@found_list, $person);
    } else {
        push(@not_found_list, $person);
    }
}

@person_list = [\@found_list, \@not_found_list];

の部分は、

foreach my $person (@person_list) {
    if ($id_list{$person->{user_id}}) {
        $person->{note} = $id_list{$person->{user_id}}->{note};
    }
}

これだけで十分である。制御変数$personを通じて、元の配列の値に操作が効くからである。