Perl/変数、データ構造

ここではPerlの変数とデータ構造についての基本的な事項を学びます。応用的な事項についてはリファレンスで触れます。
Perlでは、変数は「データを格納する領域(オブジェクト)に付けられた名前」です。 同じオブジェクトを2つ以上の変数が指し示すこともありますし、配列の要素のように、単体では名前がないオブジェクトもあります。 変数を用いることにより、データをより柔軟に扱うことができます。
変数の利用の形態は大きく分けて宣言、代入、参照の3種です。
Perlには3つの組み込みデータ型があります。
変数のデータ型は、接頭辞( sigil ; シジル)によって区別します。
スカラーは、内部に構造をもたない「ただ一つ」の値を保持できるデータ型で、接頭辞は、$(ドルマーク;Scalar の S)です。
Perlは、演算子式を評価するに当たり、演算子ごとにオペランドの型を強制的に変換します。
次のプログラムは、等価な代入演算子による実装です。
例外的に、インクリメント演算子は数値にも文字列にも作用します。
このような文字列をオペランドに取ったときのインクリメントをマジカルインクリメントと呼びます。
配列はスカラーの集合で、整数のインデックスでそれぞれの要素スカラーを参照できるデータ型で、接頭辞は、@(アットマーク;array の a)です。
当たり前のようですが、動的型付けの言語の中では、意外と少数派です。
このほか、Pythonも配列の代入は別名作成です。少数派ですが、PHPがPerlと同じです。
配列にリテラルはありません。 配列リテラル風に見えるものはリストです。
リストは、スカラー・配列やハッシュのようなデータ型ではなく書式です。
配列変数の初期化にリストが使われるので紛らわしいのですが、
リストは、複数の変数を一括宣言したり、多値代入につかわれます。
配列とリストは似通っていますが区別する必要があります。
なお、
つぎに
qw演算子を使って
qw演算子は、空白で区切った文字のシーケンスを受け取り、区切られた文字列を要素とするリストを返します。
10,4,2のように区切り文字をつけて出力したい場合、組込み関数 join を使うか、特殊変数$,を使います。
sort関数を使うと、配列を並べ替える事ができます。 並べ替えることができますが、数値の配列であっても辞書順に並べ替えてしまいます。
スライスは、配列やハッシュの部分集合へのアクセス方法を提供します。
ハッシュは、キーとなる文字列とスカラーの値がペアの集合のデータ型です。ハッシュは配列とは違って、順序は一定でないことが保証されます。 ハッシュ変数の接頭辞は % です。
Perlでは、演算子によってオペランドの型が決まるので、それに合わせて暗黙の型変換が起こります。 これは、明示的な型変換の手間を省く一方、プログラマーの意図とは異なる変換が行なわれる危うさも含んでいます。
「Hello World」 のような文字列をPerl で扱う場合、"(ダブルクォーテーション)で囲みます。
シングルクォーテーション ' ' で文字列を囲むことも出いますが、
この2点がダブルクォーテーションで囲んだ場合と異なります。
このように、Perlでは演算子がオペランドを暗黙に変換するので、演算子ごとのオペランド型の理解が大切になります。
通常、引用符で囲まれた文字列は、リテラル値として考えられていますが、Perlでは演算子として機能し、様々な種類の補間やパターンマッチの機能を提供します。 Perlでは、これらの動作のために通常の引用符が用意されていますが、任意の引用符を選択する方法も用意されています。 次の表では、{}は区切り文字のペアを表しています。
Perlの数値は、内部的にはネイティブな整数・ネイティブな浮動小数点数・数値を示す文字列で記憶します。 数値リテラルは、10進数、2進数(0bを前置), 8進数(0あるいは0oを前置), 16進数(0xを前置)によって数値を表現できます。 また、指数表現も可能です。
Perlは、数値としての非数(NaN)と無限大(Inf)をサポートしています。 ただし、大概のNaNやInfが返りそうな演算では例外が上がって来ますし、数値リテラルとしての NaN や Inf はなく、"NaN" と "Inf" をつかいます。 このとき、大文字小文字を問わず単純な先頭一致なので、以下のような少し面倒な状況がおこります。
変数 $n があるとき、 $n != $n が真なら NaN、abs($n) == "Inf" が真なら Inf または -Inf です。
Perlに限らず、数値計算には誤差が伴います。 例えば、0.01 を 100 回足しても 1 にはなりません。 これを保証する方法はいくつかありますが、ここではカハンの加算アルゴリズムを紹介します。
プログラマーが変数を宣言しなくても、いくつかの変数は機能が決まっていて、事前にPerlに用意されており、このような変数を特殊変数あるいは処理系定義済み変数と言います。
たとえば特殊変数 $0 は、プログラム名が代入されています。
変数、関数、定数などが、式の中でどのように評価されるか決定するものです。 大別するとスカラー・コンテキストとリスト・コンテキストがあり、スカラー・コンテキストにおかれた値はスカラーとして、リスト・コンテキストにおかれた値はリストとして評価されます。 コンテキストと実際のデータが食い違っている場合、次のような規則で評価されます。
どのようにコンテキストが提供されるか、以下にいくつか例を示します。
代入式は右辺に、左辺と同じコンテキストを提供します:
配列はスカラー・コンテキストで評価されるとその要素数を返すので、結果として$numberには3が代入されます。 ただしこのような結果になるのは配列だけです。 前述したとおり、リストがスカラー・コンテキストで評価されると、最後の要素が返されます:
これが $foo に代入されますが、残りの2つの変数については、対応する右辺値がない為未定義となります。 したがって、これは次のコードと等価です:
フォワード宣言されたサブルーチンは、デフォルトで引数にリスト・コンテキストを提供します:
これは次のように解釈されます。
つまり、括弧のないサブルーチン呼び出しはリスト演算子として扱われます。
もしこれを、
と解釈させたいのなら、フォワード宣言にプロトタイプを付加することによって単項演算子として解釈させることができます:
スカラー・コンテキストはさらに
に細分され、評価されます。
長さに制限のない文字列として扱われます。
数値はそのまま文字列に変換され、未定義値は空文字列になります。リファレンスも文字列になりますが、文字列として処理されたリファレンスを再びリファレンスに戻すことはできません:
数値リテラルとして解釈できる文字列は数値として扱われます。それ以外の文字があるとそこで解釈が終了します。
ifやwhileなどの制御構文や修飾文、andやorなどの論理演算子が提供するコンテキストです。
偽となるものは:
であり、残りは全て真と解釈されます。
「文字列'0'」とは'0'という文字列のことであり、数値コンテキストで0と解釈される文字列全てのことではないので注意してください。 次のものは全て真となります:
評価した結果が捨てられてしまうので、値を期待しないコンテキストです。戻り値のない関数呼び出しなど、副作用を目的として使われます。 副作用もないコードは、perlに-wスイッチをつけて実行すると警告が発せられます:
Perlでは異なるデータ型に対して同じ識別子を与えることができます:
Perl処理系は内部に識別子テーブルと呼ばれるハッシュを持っています。そのキーは識別子であり、対応する値は型グロブというデータ構造です。型グロブは同じ識別子を持つすべてのデータ型へのリファレンスを格納しています。つまり上記の例だと識別子'foo'の型グロブにはスカラー、配列、ハッシュ、サブルーチンという4つのデータ型へのリファレンスが格納されています。型グロブは識別子の前に'*'というプレフィックスを付加して表現されます:
型グロブ自身はリファレンスを格納したハッシュであり、キーはデータ型の名前です:
型グロブもデータ構造の一つですから、代入や評価ができます。型グロブに別の型グロブを代入すると、変数の別名(エイリアス)を定義することが出来ます:
これはかつてPerlにリファレンスがなかった頃、サブルーチンに引数を参照渡しするのに利用されていました。また、ファイルハンドルとフォーマットにはプレフィックスが存在しないので、これらを受け渡しする場合の唯一の手段でもありました。
現在ではリファレンスが利用できるので、型グロブを使う必要はありません。ファイルハンドルやフォーマットに関してもIOモジュールなどでオブジェクトとして扱うことができます。
なお、型グロブは識別子テーブルの実体そのものですから、ブロックに結び付けられたレキシカルスコープにすることはできません。言い換えると、local変数にはできるがmy変数にはできません。
また、特定のデータ型のリファレンスを代入すると、そのデータ型に限定して別名を定義できます: