┌──────────────────┐
│Perl入門 〜構造化プログラミング編〜 │
│(1)変数とコンテキスト │
│2005/09/03 │
└──────────────────┘
[▲Perl Home▲]
●スカラー変数
・あるプログラミング言語を使いこなすには、概要言語の「データに対する考え方」
をしっかりと把握するのが早道です。ここではPerlの3種類の変数
+ スカラー変数
+ 配列
+ ハッシュ
について、その構造を解釈していきたいと思います。
◆スカラー変数に関する疑問
・Perlのスカラー変数は、データ型によらず全ての「単一値」を格納することがで
きます。
┌──────────────────────────────────┐
$sVal = 100; # 数値
$sChr = 'a'; # 文字
$sStr = 'Taro Suzuki'; # 文字列(単一値?)
└──────────────────────────────────┘
・しかし 'a'等の1byte文字は単一値であるとしても、'Taro Suzuki'等の文字列は
単一値であると言えるでしょうか?
・しかもC言語等と異なって、特にデータ型を指定する必要も無い上に、数値/文字
を都合よく解釈させることもできます。いったい、何故こんなことができるので
しょうか。
┌──────────────────────────────────┐
$a = 100;
$b = 200;
print '数値解釈 :', $a + $b,"\n";
print '文字列解釈:', $a . $b,"\n";
───────────────────────────────────
[結果]
数値解釈 :300
文字列解釈:100200
└──────────────────────────────────┘
◆スカラー変数の構造
・恐らくですが、Perlのスカラー値は、下記のようなマルチバイトデータ構造にな
っていると想像できます。
┌──────────────────────────────────┐
データ : $a = 'あいうえお';
(データの本体)
先頭アドレス「a」: リンク時に割付
↓
┌──┐
a:│1000│→┐アドレスaが示す場所には、数値データとして
└──┘ │実データの置き場所(アドレス1000)が入っている。
│これはOS/インタープリタが与える
↓
┌─────┬─┐
1000:│あいうえお│E│
└─────┴─┘
↑
スカラー値最後を意味する番兵データ
(変数名とデータの中身)
・変数自身はデータへのアドレスである。(*1)
・「$」を付けるとアドレスが示すデータにアクセス。
・つまり、上記の例に対しては
+ aの値は「100」というアドレスを示す。
+ $aは「100番地のデータ」を意味する。(よって$は単項演算子)
・簡単に言うとC言語のポインタに近い。
└──────────────────────────────────┘
・C言語との違いでは、Cの場合変数を定義する際、その型(メモリサイズ上大きさ)
も指定します。よって宣言された型によりデータの置かれ方が異なります。例え
ば数値データとして宣言された変数は、OS/コンパイラ規定バイトのchar列とは
異なるフォーマットにてメモリ上に置かれます。当然Perlのように、ご都合主義
で数値解釈したり文字列解釈(*2)したりすることはできません。
・Perlの場合、全てのデータを文字列に近い形で認識するので、変数の演算子に応
じてデータの解釈を変えることができるようです。ただし数値データについては
それらを文字列とみなす分、メモリ確保サイズが大きくなる傾向にあると予想し
ています。
●配列
◆配列データの構造
・スカラー変数の構造から容易に類推できると思いますが、配列は文字通りスカラ
ー変数を配列にしたものです。
・先ほどスカラー変数については「C言語のポインタに近い」と説明しました。つ
まりPerlの配列は「ポインタ配列」と解釈できます。
┌──────────────────────────────────┐
@list = ('toride', 'fujishiro', 'ushiku', 'hitachinoushiku');
┌───┐ ┌───┬─┐
list+Index×0:│addr_0│-----> addr_0:│toride│E│
├───┤ ├───┴─┼─┐
list+Index×1:│addr_1│-----> addr_1:│fujishiro │E│
├───┤ ├───┬─┼─┘
list+Index×2:│addr_2│-----> addr_3:│ushiku│E│
├───┤ ├───┴─┴──┬─┐
list+Index×3:│addr_3│-----> addr_4:│hitachinoushiku │E│
└───┘ └────────┴─┘
└──────────────────────────────────┘
・上手の「Index」は「アドレスデータ格納限定」のメモリ確保サイズです。実際
に配列化されてるのは実データの置き場所アドレスデータです。
・この構造であれば、データの追加/挿入についても、実データ用のメモリ領域を
確保した後、それをアドレステーブルに登録するだけなので、リストの実装も簡
単にできると考えられます。
◆配列のスライス
・ある意味配列の一部を扱うことも可能なはず。これを「スライス」と呼びます。
・ターゲットデータとする配列のインデックスが指定できれば良いので、これを
「構文」として認識させる記述法を理解すれば良いのです。
┌──────────────────────────────────┐
@list[2,4,5] = ('kamihongo', 'minoridai', 'yahashira'); (1)
@lidx = (2, 4, 5);
@list[@lidx] = ('kamihongo', 'minoridai', 'yabashira'); (2)
※(1)と(2)は同じです。
└──────────────────────────────────┘
◆未定義のIndex
・未定義のIndexに値を設定することができます。例えば、現在の最終Indexが10だ
として、14等「間が空いて」いてもOKです。
・このとき、飛ばされた[11,12,13]インデックスは「undef」の値を持ちます。以
下に例を示します。
┌──────────────────────────────────┐
@list = ('shinden', 'minoridai', 'yabashira');
$list[4] = 'goko';
$list[6] = 'kunugiyama';
for ($i=0; $i<@list; $i++) {
if (defined($list[$i])) { # undefならfalse
print "$list[$i]\n"
} else {
print '!!undef!!',"\n";
}
}
───────────────────────────────────
[結果]
shinden
minoridai
yabashira
!!undef!!
goko
!!undef!!
kunugiyama
└──────────────────────────────────┘
◆リストの平坦化
・二つの配列
@list0 = (1, 2, 3 );
@list1 = (10, 20, 30);
があった場合、この配列を
(1, 2, (10, 20, 30), 3)
と表記すると、この配列は
(1, 2, 10, 20, 30, 3)
という一つの配列と認識されます。
・また
@lista = (@list0, @list1);
と表記しても、ソースとなる2つの配列は平坦化され
@lista = (1, 2, 3, 10, 20, 30);
と表記した場合と同じ結果になります。
・Perlの配列には、この「平坦化」があることをよく覚えておいてください。これ
は後に扱う「サブルーチン」において重要となります。
●ハッシュ
◆Perlのハッシュ
・先ほど配列の説明で「未定義のIndexに値が設定できる」と書きました。Perlの
配列は、実体データの大きさによって変わらないようにできているとすれば、
Indexの指定は自由度が高くなるでしょう。
・つまりハッシュの実装も難しくありません。keyのハッシュ整数値でIndex付けし
た配列とすれば良いのです。
◆ハッシュのスライス
・ハッシュも配列と同様にスライスが有効です。
┌──────────────────────────────────┐
%hash = ( ch4 => 'nihon',
ch6 => 'tbs',
ch8 => 'fuji',
ch10 => 'asahi',
ch12 => 'tokyo');
print "@hash{'ch4', 'ch8', 'ch12'}\n";
───────────────────────────────────
[結果]
nihon fuji tokyo
└──────────────────────────────────┘
・スライスした結果はリストとして扱うことができます。
・またエントリ値の割り当てにも適用できます。
@hash{'ch4', 'ch8'} = ('nittere', 'sankei');
●コンテキスト
◆コンテキストとは
・スカラー変数の説明にて「Perlは数値/文字を都合良く解釈する」と説明しまし
た。Perlでは、オペレータ(演算子)とオペランド(被演算子)の組み合わせを解釈
しています。
・この解釈ですが、文字通り「コンテキスト」と呼ばれています。コンテキストに
は大きく分けて2種類あり
+ スカラーコンテキスト
+ リストコンテキスト
があります。
・コンテキストは、オペレータの右辺に置かれるオペランド、又は特定のオペレー
タを使用することで決められます。
┌──────────────────────────────────┐
@list = (0,'val0',1,'val1');
$list_c = @list; # スカラーコンテキスト(要素数)
print "scalar : $list_c\n";
($list_0, $list_1) = @list; # リストコンテキスト
print "list : $list_0, $list_1\n";
%hash = @list; # リストコンテキスト
while (($key, $val) = each(%hash)) {
print "hash : $key, $val\n";
}
───────────────────────────────────
[結果]
scalar : 4
list : 0, val0
hash : 1, val1
hash : 0, val0
└──────────────────────────────────┘
◆スカラーコンテキストの種類
・スカラーコンテキストには、明示的なものとして
+ 数値コンテキスト (numeric)
+ 文字列コンテキスト (string)
そして特殊なものとして
+ ブール値コンテキスト (bool)
が存在します。
・数値/文字列コンテキストは最初に説明しているでしょう。ブール値コンテキス
トは、条件判断が論理値(ブール値)すなわち真/為として解釈するコンテキスト
です。
┌──────────────────────────────────┐
@list = ('aaa', 'bbb', 'ccc', 'ddd');
while (@list) {
$buf = shift(@list); # List要素出す
print "$buf\n";
}
───────────────────────────────────
[結果]
aaa
bbb
ccc
ddd
└──────────────────────────────────┘
・上記の例では、while中の条件判断で @list をスカラーコンテキストで受けてい
ますが、要素の有る無しをブール値として判定しています。
・コンテキストの考え方は、変数だけでなくサブルーチンの戻り値にも適用されま
す。これについては、サブルーチンのところで説明したいと思います。
・次回は、リファレンスとデータ構造を扱います。
(*1)アドレスは、データサイズに従ってダイナミックに再割付される可能性もあるので
プログラムリンク時に固定されると言い切れません。よって「ラベル」とは異なる
と考えています。
(*2)変換の関数はありますが、それは文字列として定義された変数(ポインタ)へ割り付
けねばいけません。
[▲Perl Home▲]
Copyright(c)2005 Monpe
All Rights Reserved