Perlのことを書くのは楽しいので、また書く。
Perlの初心者でかつプログラム自体にも疎いひとがPerlを習い始めて、
$scalarや@arrayが使えるようになって、
if文とforループあるいはforeachループが使えるようになり、
open IN "<hogehoge.txt"; @array = <IN>; close IN;
というのを覚えると、
それらの組み合わせでいろいろなことができるようになる。
(open関数の下りはわざと素人っぽく書いています)
原理的には、変数・条件分岐・ループが使えれば、
たぶんどんなアルゴリズムでも書けるようになるはず。
けれども、配列とfor文とif文だけを駆使してガシガシ書いていくと、
おそらく非常に冗長なコードになると思う。
複雑なことをやろうとすればするほど、
似たような配列をいくつもいくつも書いていかなければならなくなる。
それで、そういう状態が続くと、こんなことを思いつくようになる。
「配列の配列ができればいいのになー」(ぽわわわーん)
配列はこうである。
@array = ('apple', 'banana', 'orange');
で、そのぽわわわーんの配列の配列はこうである。
@array_of_array = ( ( 'Ken', 'Bob', 'Sary' ), ( 'candy', 'cookie', 'chocolate'), ( 13, 14, 12) );
配列が3つ並んでいる配列。
(仮に、この3つを@children @sweets @agesとします)
そんでもって、candyにアクセスするときは
@array_of_arrayの2番目の配列の1番目の要素、という具合にアクセスする。
そんな風なことできないかな〜、と思っている人に朗報です。
Perlには無名配列( anonymous array )というものがあります。
これを使うと、まさに、配列の配列が実現できます。
Perlでは配列にはあくまで変数(scalar)しか要素に持つことができません。
配列の要素が数字か文字か文字列かなんて気にしないPerlですが、
それが変数かどうかは気にします。
だから、配列の中に配列を突っ込もうとしても無理です。
いや、実際にはできるんだけど、それはやりたいことと違います。
@array = (@children, @sweets, @ages );
とやると、一見、一つの配列に複数の配列をぶちこんでいるようにみえますが、
実際には複数の配列をつなげて1つの配列ができるだけです。
無名配列を使って配列の配列を作るにはどうするか。
こうやります。
@array_of_ref = ( \@children, \@sweets, \@ages);
Perlにおいて配列を意味する@の直前に「 \ 」バックスラッシュをつけます。
(Macでバックスラッシュを入力するのは alt+¥ です。)
配列にバックスラッシュをつけると、
それは配列ではなく配列のリファレンスになります。
リファレンスというのが難しいかもしれませんが、
配列のリファレンスは「配列そのもの」ではなくて、
「配列の場所を指し示すもの」になります。
(reference = 参照)
配列は変数ではありません。
この場合、変数とは「単一の値をもつもの」すなわち「スカラー値」のことです。
配列は複数の値をもっています。
スカラーではなく、ベクトルだということです。
配列が配列のリファレンスになるとベクトルからスカラーになります。
配列の有る場所は1つしかありませんよね。
@array_of_refのある要素にアクセスするには以下のようになります。
$array_of_ref[0]->[1] とやるとBobになります。
ちなみに、Perlでは ] と [ に挟まれた -> は省略できるという規則があるので、
$array_of_ref[0][1]
と書いてもOKです。
ちなみに、@array_of_refもリファレンス化してしまいましょう。
$ref = \@array_of_ref;
この$refで@agesの "12" という要素にアクセスするにはどうすればいいか?
こうします。
$ref->[2]->[1] # 12
-> を省略して、
$ref->[2][1] # 12
でもOKです。
ただし、$refと[2]の間の -> は省略できません。
こうして、「リファレンス化」と「->」を駆使して
無名配列を作り、そこにアクセスします。
同じような手法で、無名ハッシュも作れますし、
無名ハッシュの無名配列の配列だってできます。
無名化(リファレンス化といってもよいかも?)を覚えると、
ソースコードの似たような変数(配列、ハッシュ含む)を劇的に減らすことができます。