リストリファレンス(参照配列)やハッシュリファレンス(参照連想配列)は Perl の鬼門だ。
リファレンス(参照)の考え方を学ぼうとした時、言語が Perl だったら多分理解する前にギブアップすると思う(笑)
Perl は変数の前にシジルと呼ばれる記号を付けて、その変数の種類(という言い方が正しいのかどうなのか)を指定する。これは Perl アンチにとっては「Perl の駄目なところ」だし、Perl 信者にとっては「Perl の良いところ」だ。
まあ、俺は好きだけどね。このお陰で、予約語と変数名がぶつかることがないので。
ちなみに、$ が付いているのがスカラー変数(文字や数値などの一つの値がセットされる変数)、@ が配列(リスト)、% が連想配列(ハッシュ)である。
しかし、これがまた Perl 初心者の人がソースを読む時の障害にもなるんだよねえ。特にリファレンスを使おうとすると、$、@、% などのシジルに加えて、リファレンスの \$、\@、\% や、デリファレンスする時の $$、@$、%$ のようなシジルも出てきてもうわやくちゃ(笑)
シジルだけで、それが配列なのか配列リファレンスなのか理解せえや!の世界だ。
リファレンスとデリファレンスの、どっちが $@ だったか \@ だったかもしばらく使ってないと忘れちゃうしね。
リファレンスの勉強がしたければ C言語とかで学ぶことをオススメします(笑)
で、いつも多重リファレンスの時の書き方アレコレを忘れてしまうので、このブログにメモっとく。
$oya ... 一番大きな配列リファレンス。つまり親。
$ko1 他 ... $oya の要素のひとつとなる配列リファレンス。つまり子。
$mago11 他 ... $ko の要素のひとつとなる連想配列リファレンス。つまり孫。
普通の配列とはリファレンスの宣言は以下のように異なる。
my @array = (); # リスト
my %hash = (); # ハッシュ
my $array = []; # リストリファレンス
my $hash = {}; # ハッシュリファレンス
各リファレンスへの値のセットと抽出の仕方を Perl のコードにしてみる。
my $oya = []; # リストリファレンスの宣言
my $ko1 = []; # リストリファレンスの宣言
my $mago11 = {}; # ハッシュリファレンスの宣言
my $mago12 = {}; # ハッシュリファレンスの宣言
my $ko2 = []; # リストリファレンスの宣言
my $mago21 = {}; # ハッシュリファレンスの宣言
$mago11->{'01'} = 'abc'; # ハッシュリファレンス mago11 に値をセット
$mago11->{'02'} = 'def'; # 〃
$mago11->{'03'} = 'ghi'; # 〃
$mago12->{'01'} = 'jkl'; # ハッシュリファレンス mago12 に値をセット
$mago12->{'02'} = 'mno'; # 〃
push @$ko1, $mago11; # 子リストリファレンスに孫ハッシュリファレンスを push
push @$ko1, $mago12; # 〃
$mago21->{'01'} = 'pqr'; # ハッシュリファレンス mago21 に値をセット
$mago21->{'02'} = 'stu'; # 〃
$mago21->{'03'} = 'vwx'; # 〃
push @$ko2, $mago21; # 子リストリファレンスに孫ハッシュリファレンスを push
push @$oya, $ko1; # 親リストリファレンスに子リストリファレンスを push
push @$oya, $ko2; # 〃
# 親リストリファレンスから子リストリファレンスの抽出
# リファレンスの要素数を確認するには、デリファレンスしてスカラー値を取得
for ($i = 0; $i < scalar(@$oya); $i++) {
# 一時リストリファレンスに子リストリファレンスをセット
my $array = [];
$array = $oya->[$i];
# 子のリストリファレンスから孫ハッシュリファレンスを抽出
# リファレンスの要素数を確認するには、デリファレンスしてスカラー値を取得
for ($j = 0; $j < scalar(@$array); $j++) {
# 一時ハッシュリファレンスに孫ハッシュリファレンスをセット
my $hash = {};
$hash = $array->[$j];
# keys でハッシュキーを抜き出すには、デリファレンスする
foreach $key(keys %$hash) {
print "キー=" . $key . " 値=" . $hash->{$key} . "\n";
}
}
}
ちなみに、上記コードではリファレンスしか使っていないが、通常の配列(リスト)に連想配列(ハッシュ)をセットするには、セットするハッシュをリファレンス化する。
my @ko1 = (); # リストの宣言
my %mago11 = (); # ハッシュの宣言
my %mago12 = (); # ハッシュの宣言
$mago11{'01'} = 'abc'; # ハッシュ mago11 に値をセット
$mago11{'02'} = 'def'; # 〃
$mago11{'03'} = 'ghi'; # 〃
$mago12{'01'} = 'jkl'; # ハッシュ mago12 に値をセット
$mago12{'02'} = 'mno'; # 〃
push @ko1, \%mago11; # ハッシュリファレンスとしてセット
push @ko1, \%mago12; # ハッシュリファレンスとしてセット
foreach $ko(@ko1) { # リストからハッシュリファレンスを1件読み出し
# keys でハッシュキーを抜き出すには、デリファレンスする
foreach $key (keys %$ko) {
print "キー=" . $key . " 値=" . $ko->{$key} . "\n";
}
}
こんな感じ。
俺的には最初から最後までリファレンスで処理するのが好み。リファレンスにしたりデリファレンスしたりしてるとわけわかんなくなる(^^;