Perl Hackers Hub

第20回 リファレンス入門(2)

この記事を読むのに必要な時間:およそ 3 分

前回の(1)こちらから。

デリファレンスのテクニック

ブレースを使ったデリファレンス

ここで,ブレースを使ったデリファンレンスの書き方を紹介しましょう。先頭に,何にデリファレンスするかを表す文字($や@など)を置き,その後ろにリファレンスを返す式をブレース{ }で囲んで置きます。たとえば,変数$arefに入っているリファレンスを配列としてデリファレンスするには,⁠@{$aref}」と書きます。

これは,先ほど紹介した「@$aref」と同じ意味です。ブレースを使った書き方では,ブレースの間に(単なる変数に限らず)任意の式を書くことができます。式は,正しいリファレンス値を返さなければなりません。

${$sref}     # スカラ変数をデリファレンス
@{&get_array_ref()} # 関数を呼び出すことも可能
${$x[2]}     # 配列の要素をデリファレンス

上記の1行目の${$sref}は,ブレースなしの書き方$$srefと同じ意味になります。しかし3行目の${$x[2]}は,ブレースを取り除いた$$x[2]とは違う意味になるので注意してください。なぜなら,$$x[2]は${$x}[2]と解釈されるためです。

図1を見てください。左側は${$x[2]}と書いた場合で,グレーの部分②が${$x[2]}を表しています。これは配列@xの添え字2にあたる要素①に入っているリファレンスを,デリファレンスしたものです。

図1 ${$x[2]}と$$x[2]の違い

図1 ${$x[2]}と$$x[2]の違い

これに対して$$x[2]と書くと,${$x}[2]と解釈されるので図1の右側のようになります。③の変数$xに入っているリファレンスを配列としてデリファレンスして,得られた配列の添え字2にあたる要素④を表します。

このようにブレースの有無によって,まったく別の意味になるので,注意しましょう。

->によるデリファレンス

配列,ハッシュ,サブルーチン(関数)のデリファレンスを行う際に,次に示すような「->」を使った書き方もできます。

  • $x->[3]は,$$x[3]を表す
  • $h->{key}は,$$h{key}を表す
  • $f->($param)は,&$f($param)を表す

また,⁠->」を連続して指定することもできます。たとえば次のようにすれば,疑似的に多次元配列や多次元ハッシュをエミュレートできます。

$x->[3]->[2]         # 多次元配列
$h->{'foo'}->{'bar'} # 多次元ハッシュ

実際には,次の例のように[ ],{ },( )は自由に組み合わせることができます。

$mix->[10]->{'abc'}

->の両側が[ ],{ },( )である場合には,->を省略できます。つまり多次元配列と多次元ハッシュをエミュレートする例は,次のように書くことができます。

$x->[3][2]
$h->{'foo'}{'bar'}

多次元配列のエミュレーション

今説明した記法を使って$x[3][2][5]のように書けば,あたかも多次元配列のように扱うことができます注4)⁠これを->を省略しないで書くと,$x[3]->[2]->[5]となります。

ここで,$xと[3]の間には->がないことに注目してください。なぜなら->を省略できるのは,その両側に[ ]や{ }がある場合だけだからです。つまり次の2つはまったく別ものとなります。

  • $x[3][2][5]は,$x[3]->[2]->[5]を表す
  • $x->[3][2][5]は,$x->[3]->[2]->[5]を表す

これらの違いを図2をもとに説明しましょう。説明を簡単にするために,図2では添え字を2次元にして,$x[2][1]と$x->[2][1]の違いを示しています。

図2 $x[2][1]と$x->[2][1]の違い

図2 $x[2][1]と$x

図2の左側は$x[2][1]です。省略された->を補ってやると$x[2]->[1]になります。これは次のように扱われます。まず配列@xの添え字2の要素①(つまり$x[2])に入っているリファレンスを配列としてデリファレンスします。そして,得られた配列の添え字1の要素②が,$x[2][1]が表しているものです。

次に,図2の右側の$x->[2][1]を見てみましょう。こちらは->を補うと$x->[2]->[1]となります。つまり,まずスカラ変数$xに入っているリファレンス③を配列としてデリファレンスします。得られた配列の添え字2の要素④に入っているリファレンスを,配列としてデリファレンスします。そして得られた配列の添え字1の要素⑤が,$x->[2][1]が表しているものです。

注4)
Perlは多次元配列をサポートしていません。

多次元配列と要素の自動生成

Perlでは配列の大きさを宣言する必要はありません。配列の要素に値を代入すると,自動的に配列の領域が確保されます。たとえば次のコードを実行すると,配列@myarrayに領域が割り当てられます。

my @myarray;
$myarray[100] = 'hello';

多次元配列風の記法$x[2][1]に対して値を代入すると,同様に自動的に無名の配列やハッシュが生成されます注5)⁠これを自動生成autovivificationと言います。

たとえば次のコードを実行すると,図3のように,配列@xの実体と2個の無名配列が生成されます。

図3 自動生成

図3 自動生成

my @x;
$x[2][1] = 100; # 無名配列A が生成される
$x[3][2] = 200; # 無名配列B が生成される

上記の2行目の代入演算子によって,配列@xの実体と無名配列Aが生成されます。そして,配列@xの添え字2の要素に,無名配列Aへのリファレンスが代入され,無名配列Aの添え字1の要素に100が代入されます。

次に3行目の代入演算子によって,無名配列Bが生成されます。そして配列@xの添え字3の要素に,無名配列Bへのリファレンスが代入され,無名配列Bの添え字2の要素に200が代入されます。

注5)
これらを無名配列,無名ハッシュと呼びます。無名配列と無名ハッシュを明示的に書く方法は次節で説明します。

著者プロフィール

近藤嘉雪(こんどうよしゆき)

読売新聞社,エル・エス・アイ ジャパン(株)などを経て,現在ヤフー(株)に勤務。エンジニアの教育などを担当している。

8080のマシン語からプログラミングを始め,大学の計算機演習でPL/Iを学び,8ビット用Cコンパイラ(LSI C-80)の開発にかかわる。その後,Perlに出会い,『Programming Perl』初版(赤ラクダ本)を翻訳する。

訳書に『プログラミングPerl 第3版』(通称:ラクダ本),『初めてのPerl 第6版』(通称:リャマ本)が(いずれもオライリー・ジャパン),著書に『yaccによるCコンパイラプログラミング』(絶版),『定本 Cプログラマのためのアルゴリズムとデータ構造,『定本 Javaプログラマのためのアルゴリズムとデータ構造』がある(いずれもソフトバンク クリエイティブ)。

URL:http://www.kondoyoshiyuki.com/
Twitter:@yoshiyuki_kondo

コメント

コメントの記入