┌──────────────────┐
│Perl入門 〜構造化プログラミング編〜 │
│(2)リファレンスとデータ構造 │
│2005/09/10 │
└──────────────────┘
[▲Perl Home▲]
●リファレンス
◆リファレンスとは
・Perlでプログラミングを、可読性の良い再利用に適したコードを組むには、サブ
ルーチンによる構造化が必要ですが、これを実践するためにはリファレンスとデ
ータ構造についての知識を持たなければいけません。
・リファレンスはデータを間接的に指す方法です。リファレンスは
+ 構造化されたコードでデータの処理を重ねる
+ データそのものを構造化する
場合に必要となります。
・変数へのリファレンス(*1)を取得するには「\(バックスラッシュ)」演算子を使
用します。
$ref_scalar = \$scalar; # スカラー
$ref_list = \@list; # リスト
$ref_hash = \%hash; # ハッシュ
┌──────────────────────────────────┐
$scalar = 'あいうえお';
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
scalar AAAA
↓ ↓
┌──┐ ┌─────┬─┐
│AAAA├──→│あいうえお│E│
└──┘ └─────┴─┘
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
$ref_scalar = \$scalar;
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
┌──┐ ┌──────┐
│BBBB├──→│AAAA:SCALAR │ ※BBBBはOS/インタプリタからの割り
└──┘ └──────┘ 当て。中身がAAAAで$scalarと同じ
↑ ↑
ref_scalar BBBB
└──────────────────────────────────┘
・リファレンスからデータの実体を取得(デリファレンス)するには、下記のような
表記(*2)を行います。
+ スカラー
${$ref_scalar} : スカラーのデリファレンス
+ リスト
@{$ref_list} : リストのデリファレンス
$ref_list->[1] : リファレンスからのリスト要素指定
+ ハッシュ
${$ref_hash} : ハッシュのデリファレンス
$ref_hash->{ele} : リファレンスからのハッシュ要素指定
┌──────────────────────────────────┐
${$ref_scalar}; # デリファレンス
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ref_scalar BBBB AAAA
↓ ↓ ↓
┌──┐ ┌──────┐ ┌─────┬─┐
│BBBB├──→│AAAA:SCALAR ├─┬→│あいうえお│E│
└──┘ └──────┘ │ └─────┴─┘
┌──┐ │
│AAAA├────────────┘※同じデータを指す
└──┘
↑
scalar
└──────────────────────────────────┘
・リスト及びハッシュのデリファレンスで使用されている「->」はアロー演算子と
呼ばれています。リファレンスからリスト要素、ハッシュ要素を参照する(*3)際
に使用します。
◆リファレンスの使用例
・ここで、リファレンス/デリファレンスを具体的なコードを通じて見ることにし
ます。
┌──────────────────────────────────┐
$scalar = 'スカラーデータ';
$ref_scalar = \$scalar;
print "ref:$ref_scalar\n";
print "deref:${$ref_scalar}\n";
print "\n";
@list = ('リスト0', 'リスト1', 'リスト2', 'リスト4');
$ref_list = \@list;
print "ref:$ref_list\n";
print 'deref[1]:', $ref_list->[1], "\n";
print "\n";
%hash = ( 'キー0' => 'ハッシュ0',
'キー1' => 'ハッシュ1',
'キー2' => 'ハッシュ2');
$ref_hash = \%hash;
print "ref:$ref_hash\n";
print 'deref{キー1}:', $ref_hash->{'キー1'}, "\n";
───────────────────────────────────
[結果]
ref:SCALAR(0x275cc4)
deref:スカラーデータ
ref:ARRAY(0x275dc0)
deref[1]:リスト1
ref:HASH(0x182dba4)
deref{キー1}:ハッシュ1
└──────────────────────────────────┘
●リファレンスとデータ構造
◆リファレンスとリスト
・複数のリストデータをハンドリングしたい場合
@list = ( ('d0', 'd1', 'd2'),
('d3', 'd4', 'd5'),
);
としても、リストは平坦化され、一つのリストと見なされます。
・つまり
@list0 = qw(d0 d1 d2); # (*4)
@list1 = qw(d3 d4 d5);
@lista = (@list0, @list1);
でも1つのリストに平坦化されてしまいます。しかし別々のリストとして扱いた
いとき、「リストの集合」として扱いたいときはリストのリファレンスを使用し
ます。
┌──────────────────────────────────┐
@list0 = qw(d0 d1 d2);
@list1 = qw(d3 d4 d5);
@lista = (\@list0, \@list1);
print '$lista[0]->[1]:',$lista[0]->[1],"\n";
print '$lista[1]->[2]:',$lista[1]->[2],"\n";
print "\n";
($r_list0, $r_list1) = @lista;
print '$r_list0->[1]:',$r_list0->[1],"\n";
print '$r_list1->[2]:',$r_list1->[2],"\n";
───────────────────────────────────
[結果]
$lista[0]->[1]:d1
$lista[1]->[2]:d5
$r_list0->[1]:d1
$r_list1->[2]:d5
└──────────────────────────────────┘
◆無名リスト
・リストのリファレンスを直接得る方法もあります。
$r_list0 = [0, 1, 2];
$r_list1 = [3, 4, 5];
・この機能を利用して、データを階層的に記述することもできます。例えば、以下
のような構造化されたデータを一つのリストで表現することもできます。
┌──────────────────────────────────┐
名簿
+------+----------+------+------------------------+-------------+
| 番号 | 氏名 | 年齢 | スキル | コメント |
+------+----------+------+------------------------+-------------+
| 0 | 山田太郎 | 20 | 速記, 珠算, 簿記 | |
| 1 | 佐藤一郎 | 22 | 情報処理, ネットワーク | |
| 2 | 山本健太 | 18 | 特殊大型, SAJ1級 | 何故SKIが? |
+------+----------+------+------------------------+-------------+
$member = [
[ # 番号[0]
'山田太郎', # 氏名 [0]->[0]
'20才', # 年齢 [0]->[1]
[
'速記', # スキル [0]->[2]->[0]
'珠算', # スキル [0]->[2]->[1]
'簿記' # スキル [0]->[2]->[2]
],
],
[ # 番号[1]
'佐藤一郎', # 氏名 [1]->[0]
'22才', # 年齢 [1]->[1]
[
'情報処理', # スキル [1]->[2]->[0]
'ネットワーク', # スキル [1]->[2]->[1]
],
],
[ # 番号[2]
'山本健太', # 氏名 [2]->[0]
'18才', # 年齢 [2]->[1]
[
'特殊大型', # スキル [2]->[2]->[0]
'SAJ1級', # スキル [2]->[2]->[1]
],
'何故SKIが?' # コメント [2]->[3]
]
];
print '1番->スキル->[1]:',$member->[1]->[2]->[1],"\n";
───────────────────────────────────
[結果]
1番->スキル->[1]:ネットワーク
└──────────────────────────────────┘
・上記のように、1つのリファレンスから構造化データを参照できるようにするこ
とは、今回はまだ説明しませんが「リファレンスカウント」を使用する際に意味
を持ちます。
◆無名ハッシュ
・先ほど構造化されたデータをリストで表しましたが、「[1]->[2]->[1]」ではち
ょっとわかりにくい部分があります。するとハッシュを使いたいと思うのが自然
です。
・リストと同様にハッシュ自身も、直接リファレンスを得ることができます。
$r_hash = {'名前' => '鈴木太郎', '年齢' => '20才'};
・すると先ほどリストで作成した「名簿」をもう少しわかりやすい形で表現するこ
とが可能になります。
┌──────────────────────────────────┐
$member = {
'山田太郎' => {
'番号' => 0,
'年齢' => '20才',
'スキル' => ['速記', '珠算', '簿記']
},
'佐藤一郎' => {
'番号' => 1,
'年齢' => '22才',
'スキル' => ['情報処理', 'ネットワーク']
},
'佐藤一郎' => {
'番号' => 2,
'年齢' => '18才',
'スキル' => ['特殊大型', 'SAJ1級'],
'コメント' => '何故SKIが?'
}
};
print $member->{'佐藤一郎'}->{'スキル'}->[1];
───────────────────────────────────
[結果]
SAJ1級
└──────────────────────────────────┘
◆データの追加
・リファレンスのハッシュ/リストについてもデータの追加変更は従来と同じよう
に行うことができます。
┌──────────────────────────────────┐
$member->{'新メンバ'} = {
'番号' => 3,
'年齢' => 24,
'スキル' => ['鬼ごっこ', '隠れんぼ'],
'コメント' => '謎のスキル...大人?'
};
print $member->{'新メンバ'}->{'スキル'}->[0];
└──────────────────────────────────┘
・ここで例を示したようにPerlではデータの構造化をC++等に比べて容易に行うこ
とができます。次回はサブルーチンの話に移っていきたいと思います。
(*1)サブルーチンのリファレンスを取得する方法もあります。
(*2)デリファレンスの表記には何種類かあるのですが、ここではMonpeの独断で「後か
ら見やすいもの」を選んで書いています。
(*3)Perlにもオブジェクト指向プログラミングの概念が存在します。このときクラス内
のメソッドや変数にアクセスする場合もアロー演算子を使用しますが、本講座では
範囲外となるため、クラスについての詳しい説明はしません。
(*4)qw関数は、クォート(データ区切り)を「,」からホワイトスペース(半角空白,Tab,
改行)に変更します。
[▲Perl Home▲]
Copyright(c)2005 Monpe
All Rights Reserved