普通、リファレンスといえば、一覧の機能参照のことですが、Perlでリファレンスといえば、言語仕様のアドレス参照のことなのです。
まぁ、PerlでのリファレンスをC言語でいえば、アドレス演算ができないポインタのようなものなのです。
リファレンスの利用場面は、私が思いつくところでは以下のケースです。
- 多次元配列を処理するケース
- 関数をリファレンスでコールするケース
- 関数の引数へ配列を渡すケース
- 関数のリターン値にするケース
◆多次元配列を処理するケース
my $array_ref1 = \@array;
配列変数の@の前に、\をつけると、配列のリファレンスが取得できます。
上記は、配列@arrayのリファレンスを$array_ref1へ格納しています。
また、無名配列のリファレンスを格納することもできます。
my $array_ref2 = [ 1, 2, 3, 4 ];
リストを [ ] でくくると、無名配列になり、そのリファレンスを$array_ref2へ格納しています。
つぎに、リファレンスから元の値を取得することをデリファレンスといいます。
my $array_ref2 = [ 1, 2, 3, 4 ]; print $array_ref2->[3]; #デリファレンス
ちなみに、『->』は矢印演算子といい、リファレンスをデリファレンスします。
補足:リファレンスの元をリファレントいいます。
つまり、$array_ref1がリファレンスで、\@arrayがリファレントです。
この機能を利用すると多次元配列の処理が可能です。
@a = ( [ qw(00 01 02) ], [ qw(10 11 12) ], [ qw(20 21 22) ]); for $i (0 .. $#a) { for $j (0 .. $#{$a[$i]}) { print '$a[' . $i . '][' . $j . ']=' . $a[$i][$j] . ' '; } print "\n"; }
尚、上記では『->』矢印演算子がありませんが、大括弧(ブラケット)や中括弧(ブレース)の間にはさまれた矢印は省略可能なのです。
◆関数をリファレンスでコールするケース
関数のリファレンスも配列と同様にできます。
sub01("aaa"); # 普通にコール $sub = \&sub01; $sub->("aaa"); # リファレンスでコール sub sub01 { print "--- sub01 $_[0]---\n"; }
『$sub = \&sub01;』で関数のリファレンスを格納して、『$sub->("aaa")』でコールしています。
◆関数の引数へ配列を渡すケース
Perlでの関数の引数はリストです。
引数に配列変数を渡すとリストに展開されてしまい、普通は上手く配列変数を渡せません。
そこで登場してくるのが配列変数のリファレンスです。
リファレンスなら、上手く配列変数を渡せるのです。
my @bbb = ("bbb", "ccc", "ddd"); my @xxx = ("xxx", "yyy", "zzz"); sub02("aaa", \@bbb, \@xxx); sub sub02 { print "--- sub02 $_[0]---\n"; print "--- sub02 $_[1]->[0]---\n"; print "--- sub02 ${$_[1]}[1]---\n"; print "--- sub02 $_[1][2]---\n"; print "--- sub02 $_[2][0]---\n"; print "--- sub02 $_[2][1]---\n"; print "--- sub02 $_[2][2]---\n"; }
◆ 関数のリターン値にするケース
関数のリターン値でblessしたリファレンスが返された場合、それは、他言語でいうオブジェクトと同じ感じになるのです。
my $date = DateString->new(); print $date->to_string, "\n"; package DateString; sub new { my $class = shift; # 第一引数は、クラス名が渡される。 my $time = shift || time(); return bless { time => $time }, $class; # blessしたリファレンスを返す。 } sub to_string { my $self = shift; return scalar localtime $self->{time}; }