Perl/リファレンス
出典: フリー教科書『ウィキブックス(Wikibooks)』
目次 |
[編集] 多次元配列
配列の中に配列が入っているものを多次元配列といいます。Perlで多次元配列を生成するには、単に配列の中に配列を入れようとしても、
@x = ("A", "B", "C"); @y = ("D", "E", "F"); @a = (@x, @y); # @b = ("A", "B", "C", "D", "E", "F")
うまくいきません。これでは@xと@yが展開され、単なる配列(一次元配列)になってしまいます。正しくは次のようにします。
@x = ("A", "B", "C"); @y = ("A", "B", "C"); @a = (\@x, \@y); print $a[0][0]; # A print $a[0][1]; # B print $a[0][2]; # C print $a[1][0]; # D print $a[1][1]; # E print $a[1][2]; # F
\@xのように、配列のシジル「@」の前に「\」を付けます。$a[0][0]とは、@aの0番目の要素 (\@x) の0番目の要素 ("A") を表します。このようにして多次元配列を生成し、多次元配列の要素にアクセスすることができます。
最初に示した例では、@xや@yが("A", "B", "C")のように展開されてしまったため、うまくいきませんでした。
@x = ("A", "B", "C"); print @x; # ("A", "B", "C");
多次元配列のようなものを作るためには、「\@x」として、「@x」という配列自体を指し示す必要があります。これは""でクォートされた文字列の中で、「"」という文字そのものを表すのに「\"」とするのと似ています。
[編集] リファレンス
リファレンスとは、あるデータが格納されている場所を指し示すデータ型です。データに「\」を前置して生成します。
$a = 42; $b = \$a;
このとき、$bには$aのリファレンスが代入されます。
$a = 42; $b = \$a; print $b;
$bを出力すると、
SCALAR(0x9d3e198)
このように表示されます。SCALARというのは、$aのデータ型がスカラであることを表しています。(0x9d3e198)は、$aが格納されている場所(メモリアドレス)を表しています。なお、0x9d3e198という数値は環境によって異なります。
$bから$aの値を取り出すには、$bに$aのデータ型であるスカラのシジル「$」を前置します。
$a = 42; $b = \$a; print $$b; # 42
さて、$bには$aのメモリアドレスが入っているということは、$aの値が変わっても、$bは常に$aの値を参照することができるのです。次の例をご覧ください。
$a = 42; $b = \$a; $a = 10000; print $$b; # 10000
これがリファレンスというものです。
$bに代入されたのは42や10000という数値そのものではなく、それらを保持している$aという変数の番地です。$$bは常に「そのとき$aに入っているもの」を表します。
スカラだけでなく、様々なデータ型のリファレンスを生成することができます。
\42; # スカラのリファレンス \$x; # スカラのリファレンス \@x; # 配列のリファレンス \%x; # ハッシュのリファレンス \&x; # サブルーチンのリファレンス \*x; # 型グロブのリファレンス \\$x; # スカラのリファレンスのリファレンス
「\」はリファレンスを生成するための単項演算子です。リファレンスそのものはスカラの一種です。
「$」や「@」のようなシジルを前置してリファレンスから元のデータを取り出すことを、デリファレンスするといいます。
リファレンスはC言語のポインタに似ていますが、より抽象的で安全だとされています。
リファレンスを使うのは、配列の配列などの複雑なデータ構造を扱う場合や、オブジェクトを扱う場合、サブルーチンに参照渡しを行う場合などに限られます。通常の配列やハッシュを使えば済む場面で、リファレンスを使うことはありません。
データを百科事典の記事の内容だとすれば、リファレンスはその記事が「何ページ目にあるか」に当たります。
[編集] スカラのリファレンス
$x = \42; print ${ $x }; # 42 print $$x; # 42 $y = \$x; # \\42 print ${ ${ $y } }; # 42 print $$$y; # 42
[編集] 配列のリファレンス
@x = ("A", "B", "C"); $a = \@x; print @$a; # ABC
回りくどいことをしなくても、要素を()の代わりに[]で囲むと、直接配列のリファレンスを生成することができます。
$a = ["A", "B", "C"]; print @$a; # ABC
配列のリファレンスの要素にアクセスするには、->を使います。
$a = ["A", "B", "C"]; print $a->[0]; # A
->を付けないと普通の配列として扱われてしまうため、->を付ける必要があります。ただし、
$a = ["A", ["B"], "C"]; print $a->[1]->[0]; # B print $a->[1][0];
最初の->以外は省略することができます。なぜならば、省略しても他の文法とぶつかることがないからです。
->を使わない方法もあります。
$a = ["A"]; print $a->[0]; # A print ${ $a }[0]; # A print $$a[0]; # A
配列の要素はスカラなので、$aに$を前置するのです。$$a[0]は${ $a[0] }ではなく、${ $a }[0]という意味です。
多次元配列でも同様です。
$a = [["A"]]; print $a->[0][0]; # A print ${ $a }[0][0]; # A print $$a[0][0]; # A
どちらを用いても構いませんが、${ $a[0] }[0]と$a[0][0]では後者のほうが見やすいとされることもあります。また変数展開コンテキストの中では、$a->[0][0]ではなく$$a[0][0]と書かなければなりません。
[編集] ハッシュのリファレンス
ハッシュのリファレンスを生成するには、次のようにします。
%a = ( a => "Apple" ); $a = \%a; print %$a; # aApple
要素を{}で囲むことで、直接ハッシュのリファレンスを生成することができます。
$a = { a => Apple }; print %$a; # aApple
%$aは通常のハッシュと同じように扱うことができます。ハッシュの値にアクセスするには、次のようにします。
$a = { a => "Apple" }; print $a->{a}; # Apple print ${ $a }{a}; # Apple print $$a{a}; # Apple
$a->{a}->{a}は$a->{a}{a}と書くことができます。
[編集] オブジェクト指向におけるリファレンス
Perl/ライブラリ・モジュールとオブジェクト指向の項で扱います。