サブルーチンの引数としてリファレンスを受け取るようにすると、呼び出し元でパラメータとして渡した変数の値を変更することができます。
サブルーチンの呼び出し側でも意識してリファレンス(例: \$val
)を渡すようにする必要があります。
C/C++ のポインタとほぼ同様の概念です。
# 渡された引数の中身を変更する
sub replace_value {
my($ref) = @_; # スカラ変数のリファレンスを受け取る
$$ref = 200; # デリファレンスして代入すると呼び出し元のスカラ変数を変更
}
my $val = 100;
&replace_value(\$val); # 呼び出し側ではリファレンスを渡す
print $val; #=> 200
# 渡された配列に値を追加する
sub push_something {
my($ref_array) = @_; # 配列変数のリファレンスを受け取る
push @$ref_array, 100; # 呼び出し元の配列を変更
}
my @arr;
&push_something(\@arr); # 呼び出し側ではリファレンスを渡す
&push_something(\@arr); # 〃
&push_something(\@arr); # 〃
print "@arr\n"; #=> '100 100 100'
リファレンス自体はスカラ値として扱われるので、配列のリファレンスを渡した場合も $ref_array
のように $
の付いた変数名となることに注意してください。
このリファレンスをデリファレンスするときは、配列として扱うので、@$ref_array
のように @
を付けてデリファレンスすることになります。
例えば、次のように配列をリファレンスでサブルーチンに渡した場合、
hoge(\@arr);
次のように shift
で取り出した配列リファレンスをデリファレンスして参照しようとするのは間違いです。
sub hoge {
my @arr = @{shift}; # NG! これでは @shift という配列変数を参照してしまう
}
@{shift}
が、変数 @shift
ではないということを知らせるために何らかの工夫をしなければいけません。
例えば、以下のようにすれば、正しく shift
で取り出した値をデリファレンスしてくれます。
my @arr = @{shift()};
my @arr = @{+shift};
参考: 『Effective Perl』