perldata - Perl のデータ型
(変数名)
Perl には、スカラ、スカラの配列、「ハッシュ」とも呼ばれるスカラの 連想配列という 3 つの組み込みデータ型があります。 スカラは単一の(任意の長さの)文字列(利用可能メモリによってのみ制限されます)か、 数値か、何かへのリファレンス(これは perlref で議論します)のいずれかです。 通常の配列は 0 を基点とする数値で添え字づけされるスカラの順序付き リストです。 ハッシュ配列は、文字列のキーのインデックスと、それに結び付けられた スカラ値の、順序のない集合です。
値は通常、名前もしくは名前付きのリファレンスを通して参照されます。
名前の最初にある文字は、その名前がどのような構造のデータを
参照しているのかを区別します。
名前の残りの部分は、参照する値を特定するものです。
通常、この名前は一つの 識別子、つまり、英字か下線から始まって
それに英字、下線、数字が続く文字列のことです。
一部のケースにおいては ::(あるいはやや古風な ') で分けられた
識別子の並びであってもかまいません。
これの最後のもの以外の名前は、最後の部分にある識別子を
その名前空間に置くためのパッケージの名前として解釈されます
(詳細は perlmod/Packages を参照してください)。
リファレンスを生成する式の単純な識別子を、実行に値に置き換えることも
可能です。
これはこの文書の後の部分と、perlref に詳細な説明があります。
identifier
Perl はこれらの規則に従っていない名前を持っている組み込みの変数も
持っています。
これらは変わった名前をもっているので、あなたが使った普通の
変数との間で間違って衝突することがありません。
正規表現の括弧づけされた部分(parenthesized parts)の文字列は $ の後に
数字だけが続いている名前で保存されます( perlop と perlre を
参照してください)。
それに加え、Perl の内部的な動作に対する窓を開けている幾つかの
特殊変数が、句読点文字と制御文字を含む名前を持っています。
これらは perlvar で文書化されています。
variable, built-in
スカラ値の参照は、配列やハッシュの一要素であるスカラを参照する場合でも、 常に名前に '$' を付けます。 シンボル '$' は文法的に英単語 "the" のように働き、単一の値が 想定されていることを示しています。 scalar
$days # the simple scalar value "days"
$days[28] # the 29th element of array @days
$days{'Feb'} # the 'Feb' value from hash %days
$#days # the last index of array @days
配列全体(および配列やハッシュのスライス)は '@' で示します; これは英単語での "these" や "those" のように働き、複数の値が 想定されていることを示します。 array
@days # ($days[0], $days[1],... $days[n])
@days[3,4,5] # same as ($days[3],$days[4],$days[5])
@days{'a','c'} # same as ($days{'a'},$days{'c'})
ハッシュ全体は '%' で示します: hash
%days # (key1, val1, key2, val2 ...)
さらに、サブルーチンは名前の前に '&' を付けて示しますが、英語でもほとんど 使われなくなった "do" のように、曖昧にならなければ、省略できます。 シンボルテーブルのエントリは、名前に '*' を付けて示すことができますが、 (気にする気があっても :-)まだ気にする必要はありません。
変数のすべての型には、いくつかの変数でない識別子と同様、
それぞれの名前空間があります。
これは、衝突を心配せずに、スカラ変数、配列、ハッシュ -- さらに
ファイルハンドル、ディレクトリハンドル、サブルーチン名、フォーマット名、
ラベルに、同じ名前を付けることができることを意味します。
つまり、$foo と @foo は 2 つの異なる変数であるということです。
また、$foo[1] は @foo の一部であって、$foo の一部ではありません。
少々奇妙に思えるかもしれませんが、それで良いのです;
奇妙なのですから。
namespace
変数の参照は、いつも '$'、'@'、'%' で始まりますから、「予約」語は、
変数名としては、本当の意味で予約されているわけではありません。
しかしながら、先頭に特別な文字を付けない、ラベルやファイルハンドルとしては、
予約されている ことになります。
たとえば、"log" といった名前のファイルハンドルを使うことはできません。
ヒント: open(log,'logfile') などではなく、
open(LOG,'logfile') としてください。
大文字のファイルハンドルを使えば、読みやすくもなりますし、
将来に渡る予約語との衝突も避けられます。
大文字と小文字は 区別されます から、"FOO"、"Foo"、"foo" は、
すべて違う名前です。
英字と下線で始まる名前は、名前の一部に数字や下線を
含むことができます。
identifier, case sensitivity
case
そのような英数字の名前を、適切な型へのリファレンスを返す式で 置き換えることも可能です。 詳しくは、perlref を参照してください。
数字で始まる名前には、数字しか含めることができません。
英字、下線、数字、キャレット(制御文字)以外の文字で始まる名前は、
$% や $$ のように 1 文字に限定されます(これら 1 文字の名前の多くは、
Perl があらかじめ意味を定めています。
たとえば、$$ はカレントプロセスのプロセス ID を示します)。
(コンテキスト)
Perl における演算や値の解釈は、その演算や値の置かれたコンテキストからの 要求に依存する場合があります。 このコンテキストというものには大きく二つあり、リストコンテキストと スカラコンテキストと呼ばれます。 リストが要求されるコンテキストではリスト値を返し、 そうでなければスカラ値を返すような演算も存在します。 そのような演算については、ドキュメントでその演算に触れるときに 付記しています。 言い方を変えると、Perl では、ある種の演算が一つの値を返して欲しいか、 複数の値を返して欲しいかによって多重定義されているということです。 "fish" や "sheep" といった、単複同形の英単語と似ているかもしれません。
逆に演算子は、その引数がスカラコンテキストかリストコンテキストの いずれかで解釈されるかを決めてしまいます。 例えば、以下のようにすると:
int( <STDIN> )
int 演算子は、自分の引数である <> 演算子がスカラコンテキストで 評価されることを期待するため、STDIN から一行を読み出して int 演算子に渡します。 int 演算子は、その行から整数値を取り出して返すことになります。 これに対して、以下のようにすると:
sort( <STDIN> )
sort 演算子は <> 演算子がリストコンテキストで評価されるために 、 <> は STDIN から読める限り最後の行まで読み出して、 そのリストを sort のルーチンに渡します。 sort ルーチンは受け取った行のリストをソートし、その結果のリストが 戻り値となります。
代入演算は少し特殊です。 代入では、右引数のコンテキストを決めるために左引数が使われます。 スカラへの代入では、右側をスカラコンテキストで評価しますが、 配列やハッシュに対する代入では、右側をリストコンテキストで 評価することになります。 リスト(あるいはスライス; 要するにリストですが)への代入も、 右側をリストコンテキストで評価することになります。
use warnings プラグマや Perl の -w コマンドラインオプションを使うと、
「無効コンテキスト」での定数や関数の無意味な使用について警告が出ます。
無効コンテキストは、"fred"; や getpwuid(0); のみを含む文のように、
単に値が捨てられることを意味します。
リストコンテキストで呼び出されたかどうかを考慮する関数にとっては、
これはやはりスカラコンテキストとして扱われます。
ユーザが定義するサブルーチンは、自分が無効、スカラ、リストのどの コンテキストで呼ばれたかを意識することができます。 しかし、多くのサブルーチンでは意識する必要もないでしょう。 スカラ値とリストは自動的にリストに展開されるからです。 関数が呼び出されたコンテキストを動的に識別する方法については、 perlfunc/wantarray を参照してください。
(スカラ値)
Perlにおける全てのデータは、スカラか、スカラの配列か、スカラの ハッシュとなります。 スカラは、数値、文字列、リファレンスのいずれか一つの値を保持します。 一般的には、ある種類から他の種類への変換は透過的です。 スカラは直接複数の値を保持することはできませんが、複数の値を保持している 配列やハッシュに対するリファレンスを保持することができます。
スカラは何かであることを宣言する必要はありません。 あるスカラ変数が、「文字列」型、「数値」型、「リファレンス」型、 あるいはその他の型であるように宣言する方法はありません。 これは、スカラ、スカラを返す操作の自動変換はその呼び出し元が 文字列、数値、リファレンスのどれを対象にしているのかを気に する必要がない(実際は、気にすることができない)ためです。 Perl はスカラが文字列、数値、リファレンス (オブジェクトを含みます)を 保持することのできる文脈的多態言語 (contextually polymorphic language) です。 文字列と数値は、ほとんど全ての目的に対して適当であるように思われますが、 リファレンスは組み込みのリファレンスカウントとデストラクタとを 持っている、キャストすることのできない強く型付けされたポインタです。
スカラ値は、その値が空文字列か数値の 0 (あるいは同値な文字列 "0") 以外の場合には、真偽値の真として扱われます。 真偽値コンテキストは、単に文字列や数値への変換が行われなかった 特別なスカラコンテキストとして扱われます。 boolean bool true false truth
空文字列には、実は定義済みと未定義の 2 種類があります。
定義済みの値は "" のような、単に長さ 0 の文字列です。
未定義の空文字列は、エラーがあったときや、ファイルの終わりに達したとき、
初期化していない変数や配列やハッシュの要素を参照したときなど、
何かに対する実際の値が存在しないことを示します。
初期のバージョンの Perl では、未定義のスカラは、最初に定義済みで
あるかのように使ったときに定義済みとなり得ますが、これはもはや、
perlref で説明している自動有効化が起きる稀な場合を除いて、起こりません。
値が定義済みであるかどうかを調べるために defined() 演算子を
使うことができ(これは配列やハッシュに対しては無意味です)、
未定義値を生成するために undef() 演算子を使えます。
defined undefined undef null string, null
与えられた文字列が正当な非ゼロの数値であるかどうかを確かめるには、 数値の 0 か lexical な "0" に対してテストすれば十分な場合もあります (もっともこれは警告が有効ならノイズを引き起こします)。 数値ではない文字列は、awk のように 0 とはみなすことはしないからです:
if ($str == 0 && $str ne "0") {
warn "That doesn't look like a number";
}
このメソッドは最良です; なぜなら、さもなければ NaN や
Infinity のような IEEE 記法の 属性を扱えないからです。
その他の場合、データが数値であるかどうかを検査するためには、
POSIX::strtod() 関数を呼び出すか、(perlre に記述されているように)
正規表現を使って文字列を調べるとよいでしょう。
warn "has nondigits" if /\D/;
warn "not a natural number" unless /^\d+$/; # rejects -3
warn "not an integer" unless /^-?\d+$/; # rejects +3
warn "not an integer" unless /^[+-]?\d+$/;
warn "not a decimal number" unless /^-?\d+\.?\d*$/; # rejects .2
warn "not a decimal number" unless /^-?(?:\d+(?:\.\d*)?|\.\d+)$/;
warn "not a C float"
unless /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/;
配列の大きさはスカラ値です。 配列 @days の大きさは、csh のように $#days を評価するとわかります。 しかし、これは大きさではありません; 最後の要素に対する添え字になり、通常は 0 番目の要素があるので違う値に なります。 $#days に代入を行なうと実際の配列の大きさも変化します。 この方法で配列を小さくすると、見えなくなった部分の値は破壊されます。 小さくした配列を再び大きくしても、以前存在した要素に対する前の値が 回復することはありません。 (Perl 4 では回復可能でしたが、デストラクタが期待通りの時点で 呼ばれることを保証するために、これを止めました。) $# array, length
大きくなるであろう配列をあらかじめ大きくしておくことで、 ほんの少しだけ効率を向上させることもできます。 最後の要素よりも後ろに離れた位置に代入を行なうことでも、 配列を大きくすることができます。 配列に空リスト () を代入すると、何も無い状態にまで切り詰められます。 以下の二つは等価です:
@whatever = ();
$#whatever = -1;
配列をスカラコンテキストで評価すると、配列の大きさが返されます。 (これはリストに対しては成り立たないことに注意してください。 この場合には、C のカンマ演算子と同じように最後の値が返され、 組み込み関数のように値を返すことはしません。) 以下の式は常に真となります: array, length
scalar(@whatever) == $#whatever - $[ + 1;
Perl バージョン 5 では $[ の意味を変更しました:
$[ を設定していないファイルにおいて、他のファイルがこの変数を
変更しているかどうかを心配する必要がなくなりました
(言い換えると、$[ は使わないほうが良いと言うことです)。
ですから、普通は以下のようになります。
$[
scalar(@whatever) == $#whatever + 1;
一部のプログラマは、曖昧さをなくすために明示的に変換することを 選ぶでしょう:
$element_count = scalar(@whatever);
ハッシュをスカラコンテキストで評価した場合、ハッシュが空のときにだけ
偽が返されます。
キー/値のペアが登録されていれば、真を返します。
より正確には、返される値は使用しているエントリの数と、
割り付けられているエントリの数を、スラッシュで区切った文字列です。
これは、与えたデータに対して、Perl の内部のハッシュのアルゴリズムが、
うまく動作しないかを確認するときくらいにしか使えませんが。
たとえば、ハッシュに 10,000 個 のものを入れ、%HASH をスカラコンテキストで
評価したときに 1/16 が得られれば、16 のうち一つのエントリだけが使われ、
おそらくそこに 10,000個 すべてが入っていることを意味します。
これはほとんど起こりそうもないことです。
tie したハッシュがスカラコンテキストで評価されると、この使用バケツ情報は
現在のところ tie したハッシュでは利用できないので、致命的エラーとなります。
hash, scalar context hash, bucket bucket
keys() 関数に代入をすることによって、ハッシュのためにあらかじめ スペースを割り当てることができます。 その際に、割り当てる要素の数はその数値以上で最小の 2 のべき乗に 丸められます:
keys(%users) = 1000; # 1024要素割り付ける
(スカラ値のコンストラクタ)
数値リテラルは、以下の浮動小数点数と整数の形式で示されます:
12345
12345.67
.23E-10 # a very small number
3.14_15_92 # a very important number
4_294_967_296 # underscore for legibility
0xff # hex
0xdead_beef # more hex
0377 # octal (only numbers, begins with 0)
0b011011 # binary
数値リテラルを読みやすくするために、数字の間に下線を使えます。 例えば、(Unix 式のモード引数のために、0b110_100_100 のように) 2 進数を 3 桁ごとにグループ分けしたり、(ニブルを表現するために、0b1010_0110 のように) 4 桁ごとにグループ分けしたり、あるいはその他の方法でグループ分け出来ます。 number, literal
文字列リテラルは、シングルクォートかダブルクォートで区切られます。
これらは、標準 Unix シェルのクォートと同じように扱われます:
ダブルクォートの文字列リテラルでは、バックスラッシュの置換と
変数の置換が行なわれ、シングルクォートの文字列では、
(\' と \\を除いて)これらの置換は行なわれません。
普通の C 形式でのバックスラッシュの置換規則は、改行やタブを始め、ある種の
変わった形式のためにも使われます。
詳しくは perlop/"Quote and Quote-like Operators" を参照してください。
string, literal
文字列リテラルの中で ('0xff' のように) 16 進、8 進、2 進で 表現されたものは、その値が表すものに自動的に変換されることはありません。 hex() や oct() といった関数がそのための変換を行います。 詳しくは perlfunc/hex と perlfunc/oct を参照してください。
また、文字列に直接、改行を埋め込むこともできます。 つまり、文字列は、開始した行で終了する必要はないと言うことです。 これは素晴らしいのですが、終了のクォートを付け忘れた場合には、 次にクォート文字が見つかるまでの間、Perl はエラーを 見つけることができなくなります。 それは、スクリプト上でずっと先になるかもしれません。 文字列中での変数の置換は、スカラ変数、配列、配列やハッシュのスライスに 限定されています(言い換えると、$ や@ で始まる識別子か、それに 大かっこで括った添え字をつけたものです)。 次のプログラムは "The price is $100." と印字します。 interpolation
$Price = '$100'; # not interpolated
print "The price is $Price.\n"; # interpolated
Perl では二重展開は行われないので、$100 はそのままになります。
デフォルトでは、文字列に置換された浮動小数点数は小数点としてドット (".") を
使います。
use locale が有効で、POSIX::setlocale() が呼び出されている場合、
小数点として使われる文字は LC_NUMERIC ロケールによって影響を受けます。
perllocale と POSIX を参照してください。
いくつかのシェルと同じように、変数名の前後に中かっこを入れて、 つながっている英数字(および下線)から切り離せます。 変数を文字列に展開する時に、後に続くコロン 2 つやシングルクォートと 変数名を分割する場合にもそうしなければなりません; さもなければパッケージのセパレータとして扱われるからです:
$who = "Larry";
print PASSWD "${who}::0:0:Superuser:/:/bin/perl\n";
print "We use ${who}speak when ${who}'s here.\n";
中かっこなしでは、Perl は変数 $whospeak, $who::0, $who's を探します。
後ろ二つは、(おそらく)存在しないパッケージ who の変数 $0 と $s に
なります。
実際には、そのような中かっこの内側にある識別子は、ハッシュの添え字に
ある識別子と同様、強制的に文字列になります。
どちらもクォートは必要ありません。
先の例にあった、$days{'Feb'} は $days{Feb} のように書くことができ、
自動的にクォートが仮定されます。
しかし、添え字により複雑な何かを使っている場合には式として解釈されます。
これは例えば、$version{2.0}++ は $version{2}++ と等価であり、
$version{'2.0'}++ ではないということを意味します。
(バージョン文字列)
注意: バージョン文字列 (v-文字列) は非推奨です。 これは Perl 5.8.1 以降のいつか未来のリリースで削除されます。 v-文字列のわずかな利点より、潜在的な驚きと混乱の方が大きく上回ります。
v1.20.300.4000 の形のリテラルは、指定された序数を持つ文字からなる
文字列としてパースされます。
この形はv-文字列と呼ばれ、より読みにくい文字変換形式
"\x{1}\x{14}\x{12c}\x{fa0}" よりも読みやすい文字列を構成する方法を
提供します。
これは Unicode 文字列を表現するためや、バージョン「番号」を文字列比較
演算子 cmp, gt, lt などを使って比較するときに便利です。
もしリテラルに 2 つ以上のドットがある場合、先頭の v は省略できます。
print v9786; # prints SMILEY, "\x{263a}"
print v102.111.111; # prints "foo"
print 102.111.111; # same
このようなリテラルは require と use でバージョンチェックを行う場合に
受け入れられます。
v-文字列を IPv4 アドレスに使うと、Socket パッケージの
inet_aton()/inet_ntoa() ルーチンも使わない限り、移植性がないことに
注意してください。
Perl 5.8.1 から、 (v65 のような) 単一の数値のv-文字列は => 演算子
(ハッシュキーとハッシュの値を分けるために普通使われます) の前では
v-文字列ではなく、リテラル文字列 ('v65') として扱われることに
注意してください。
これは Perl 5.6.0 から Perl 5.8.0 ではv-文字列でしたが、これはよいことよりも
大きな混乱と破壊を招きました。
v65.66 や 65.66.67 のような複数の数値の v-文字列 は常にv-文字列で
あり続けます。
(特殊なリテラル)
__FILE__, __LINE__, __PACKAGE__ という特殊なリテラルはそれぞれ、
カレントのファイル名、行番号、パッケージ名を表わします。
これらは独立したトークンとしてのみ用いられます;
文字列中に展開されることはありません。
(空の package; 指示子によって)カレントパッケージが存在しない場合、
__PACKAGE__ は未定義値となります。
__FILE__ __LINE__ __PACKAGE__ line file package
二つの制御文字 ^D と ^Z、およびトークン __END__ と __DATA__ は、 実際のファイルの終端より前にある論理的なスクリプトの終端を示すために 使うことができます。 これらの後にあるテキストは無視されます。
しかし、__DATA__ 以降のテキストはファイルハンドル PACKAGE::DATA を
通して読み出すことができます; ここで PACKNAME は __DATA__ トークンに
遭遇した時点でのカレントのパッケージ名です。
ファイルハンドルは __DATA__ の後の内容を指して開かれたままです。
ここからデータを読み終わったら close DATA するのはプログラムの責任です。
__DATA__ が導入される前に書かれた古いスクリプトとの互換性のために、
__END__ は、スクリプト(但し require や do で読み込まれたファイルでは
ないもの)のトップレベルでの __DATA__ のように振る舞い、
ファイルの残りの内容は main::DATA でアクセス可能なままになります。
__DATA__ の詳細とそれをつかった例は SelfLoader を参照してください。 BEGIN ブロックでは、ファイルハンドル DATA から読み出せないことに 注意してください。 BEGIN ブロックはそれが見つかった時点で即実行されるので、 __DATA__(や __END__)トークンがどこにあるのかがわからないのです。
(裸の単語)
文法的に別の解釈ができない単語は、クォート文字列であるかのように
扱われます。
これは“裸の単語”(barewords)と呼ばれます。
ファイルハンドルやラベルと同様に、小文字だけからなる裸の単語は将来、
予約語とぶつかる危険があります。
そのような単語があった場合、use warnings プラグマや
-w スイッチをつけることでPerl がそのような単語を指摘してくれます。
裸の単語をなくして欲しいという人もいます。
以下のようにすると:
use strict 'subs';
サブルーチンコールと解釈できない裸の単語がコンパイル時にエラーとなります。
この制約は囲っているブロックの終わりまで有効です。
内側のブロックで no strict 'subs'と書くことで、この機能を
撤回することもできます。
(配列を結合するデリミタ)
配列とスライスは、ダブルクォート文字列中で、要素を変数 <$">
("use English;" が指定されていれば $LIST_SEPARATOR) 中に
示す区切り文字(デフォルトはスペース) でつなげて展開されます。
以下は等価です:
$temp = join($", @ARGV);
system "echo $temp";
system "echo @ARGV";
検索パターン (ここでも、ダブルクォートのような置換が行なわれます) の中では、
解釈する上で不幸な曖昧さがあります。
/$foo[bar]/ は、/${foo}[bar]/ と解釈される
(この場合 [bar]は、正規表現の文字クラス) のでしょうか?
/${foo[bar]}/ と解釈される (この場合 [bar] は、
配列 @foo の添え字) のでしょうか?
@foo が他に存在しない場合には、明らかに文字クラスとなります。
@foo が存在すれば、Perl が [bar] の意味に見当をつけますが、たいてい
正しい解釈をします。
もし見当があたっていないときや偏執的にこだわりたい時には、上に
書いたように中かっこを付けて強制的に解釈のしかたを決めることができます。
以前ここにあった、ヒアドキュメントの使い方に関する情報を探しているのなら、 その情報は perlop/Quote and Quote-like Operators に移動しました。
(リスト値のコンストラクター)
リスト値は、個々の値をコンマで区切って (必要に応じて括弧で括って) 示されます:
(LIST)
リスト値が要求されていないコンテキストでは、リストリテラルのように みえる値の場合は、C のコンマ演算子の場合のように、単に最後の要素の 値が使われます。 例えば:
@foo = ('cc', '-E', $bar);
これはリスト値全体を配列 @foo に代入しますが:
$foo = ('cc', '-E', $bar);
これは変数 $bar の値をスカラ変数 $foo に代入します。 本物の配列がスカラコンテキストで評価されたときの値は、 その配列の大きさとなります。 以下の例では、$foo に 3 という値が代入されます:
@foo = ('cc', '-E', $bar);
$foo = @foo; # $foo gets 3
リストリテラルの閉じ括弧の前には余分にコンマを置いてかまいませんので、 以下のように書くことができます:
@foo = (
1,
2,
3,
);
配列への代入にヒアドキュメントを使うには、要素毎に 1 行となり、 以下のような手法が使えます:
@sauces = <<End_Lines =~ m/(\S.*\S)/g;
normal tomato
spicy tomato
green chile
pesto
white wine
End_Lines
リストの中にリストがある場合には、自動的に展開されてしまいます。 これは、外側のリストが評価されると、リストの個々の要素がリストコンテキストで 評価され、その結果のリスト値の個々の値が、元のリストの要素であるかのように 展開されるのです。 つまり、リストの中では配列もハッシュも、その性質が現れてきません -- 以下のリストは
(@foo,@bar,&SomeSub,%glarch)
@foo のすべての要素の後に @bar のすべての要素を続け、 その後に SomeSub というサブルーチンが返すすべての要素を続け、 最後に %glarch のキー/値のペアを続けたものを要素として持ちます。 展開 されない リストのリファレンスを作るためには、perlref を 参照してください。
空リストは () で表わされます。 リスト中で空リストを展開しても何も起こりません。 つまり、 ((),(),()) は () と等価です。 同様に、要素のない配列を展開することは、その場所に何も 展開しなかったのと同じことになります。
この展開は、開きかっこと閉じかっこは(優先順位のための必要性がなければ)
省略可能であるということと、リスト中に複数のカンマがあっても文法的に
有効なので、リストの最後に追加のカンマをつけられるということを
組み合わせたものです。
リスト 1,,3 は 2 つのリスト 1, と 3 の結合であり、
1 つ目のリストはオプションのカンマで終わっています。
1,,3 は (1,),(3) で 1,3 です (そして同様に 1,,,3 は
(1,),(,),3 で 1,3 です。以下同様。)
この暗黒面を使うよう勧めているわけではありません。
リスト値にも通常の配列と同じように、添え字をつけることができます。 リストには、曖昧さをなくすために、括弧を付けなくてはなりません。 例:
# Stat returns list value.
$time = (stat($file))[8];
# SYNTAX ERROR HERE.
$time = stat($file)[8]; # OOPS, FORGOT PARENTHESES
# Find a hex digit.
$hexdigit = ('a','b','c','d','e','f')[$digit-10];
# A "reverse comma operator".
return (pop(@foo),pop(@foo))[0];
リスト自身を構成する個々の要素すべてに代入が許される場合にのみ、 全体のリストに代入を行なうことができます:
($a, $b, $c) = (1, 2, 3);
($map{'red'}, $map{'blue'}, $map{'green'}) = (0x00f, 0x0f0, 0xf00);
この例外として、リストにundefを代入することもできます。
これは関数の戻り値の一部を捨て去るのに便利です:
($dev, $ino, undef, undef, $uid, $gid) = stat($file);
スカラコンテキスト中のリスト代入は、代入の右辺にある式によって 生成された要素の数を返します:
$x = (($foo,$bar) = (3,2,1)); # set $x to 3, not 2
$x = (($foo,$bar) = f()); # set $x to f()'s return count
これはブールコンテキストでリストの代入をしたいときに便利です。 なぜなら、ほとんどのリスト関数は終了時に空リストを返すからです。 これは代入が 0 を生成したときには、偽と解釈されます。
これはまた、関数の実行や操作の処理をリストコンテキストで行い、 それからそれを空リストにからすからコンテキストでの代入を行うことで 返り値の数を数えるための便利な慣用法のもととなります。 例えば、以下のコードは:
$count = () = $string =~ /\d+/g;
$string の中で見つかった数字のグループの数を $count に設定します。 これは、(値が空リストに代入されているので)パターンマッチングは リストコンテキストで行われ、従って文字列での全てのマッチした部分の リストが返されるために起こります。 スカラコンテキストでのリスト代入は要素数(ここでは、マッチしたパターンの 数)に変換され、それが $count に代入されます。 単に以下のようにしても:
$count = $string =~ /\d+/g;
うまく動かないことに注意してください; スカラコンテキストでの パターンマッチングはマッチした数ではなく、単に真か偽を返すからです。
リスト代入の最後の要素は、配列やハッシュでもかまいません:
($a, $b, @rest) = split;
my($a, $b, %rest) = @_;
実際は、リストの任意の要素として配列を使うことができますが、 リスト中の最初の配列が、右辺の値をすべて取り込んでしまうため、 それ以降のものは未定義になります。 これは、my() や local() では有用かもしれません。
ハッシュはキーと値と解釈される値のペアとなるリストリテラルを使って 初期化されます:
# same as map assignment above
%map = ('red',0x00f,'blue',0x0f0,'green',0xf00);
しばしば、リストリテラルと名前付きの配列は互いに交換可能ですが、 ハッシュの場合はそうではありません。 通常の配列がハッシュとしてリスト値で添え字づけできないのと同様に、 リスト値を使って添え字づけすることはできません。 同様に、その一部として別のリストを含むハッシュ(パラメーターリストや 関数の戻り値リストを含みます)は常に平坦なキー/値のペアにされます。 これはリファレンスをきちんと使う理由です。
key/value のペアの間に => 演算子を使うと読みやすくなります。
=> 演算子は実質、見た目に判別しやすいカンマ演算子でありますが、
その左側にあるオペランドが正当な単純な識別子であるような
裸の単語であるときに、それを文字列として解釈するようになっています
(=> は、2 つのコロンを含むような複合識別子はクォートしません)。
これは、ハッシュの初期化を格好よいものにします:
%map = (
red => 0x00f,
blue => 0x0f0,
green => 0xf00,
);
あるいは、レコードとして使うハッシュリファレンスを初期化するために 使います:
$rec = {
witch => 'Mable the Merciless',
cat => 'Fluffy the Ferocious',
date => '10/31/1776',
};
複雑な関数のために名前付きパラメータによる呼び出しを使うためにも 使えます:
$field = $query->radio_group(
name => 'group_name',
values => ['eenie','meenie','minie'],
default => 'meenie',
linebreak => 'true',
labels => \%labels
);
ハッシュでは順番に意味がないので、初期化の順序にも意味はないということに 注意してください。 出力の順序を変える方法の例は、perlfunc/sort を参照してください。
(添え字)
配列は、ドル記号 ($)、(先頭の @ なしの)配列名、大かっこで囲われた
添え字、の順で指定することで添え字付けされます。
例:
@myarray = (5, 50, 500, 5000);
print "Element Number 2 is", $myarray[2], "\n";
配列の添え字は 0 から始まります。
負数の添え字は後ろから値を取り出します。
前述の例では、$myarray[-1] は 5000 となり、$myarray[-2] は
500 となります。
ハッシュの添え字も同様ですが、大かっこの代わりに中かっこを使います。 例:
%scientists =
(
"Newton" => "Isaac",
"Einstein" => "Albert",
"Darwin" => "Charles",
"Feynman" => "Richard",
);
print "Darwin's First Name is ", $scientists{"Darwin"}, "\n";
(スライス)
配列やハッシュにアクセスする一般的な方法は、一度に一つのスカラ要素です。 リストから一つの要素を取り出すためにも、添え字を使えます。
$whoami = $ENV{"USER"}; # one element from the hash
$parent = $ISA[0]; # one element from the array
$dir = (getpwnam("daemon"))[7]; # likewise, but with list
スライスは、添え字のリストを使ってリスト、配列、ハッシュの複数の要素に 同時にアクセスします。 これはそれぞれの要素を個々のスカラ値のリストとして扱うより便利です。
($him, $her) = @folks[0,-1]; # array slice
@them = @folks[0 .. 3]; # array slice
($who, $home) = @ENV{"USER", "HOME"}; # hash slice
($uid, $dir) = (getpwnam("daemon"))[2,7]; # list slice
変数のリストに代入できるので、配列やハッシュのスライスにも代入できます。
@days[3..5] = qw/Wed Thu Fri/;
@colors{'red','blue','green'}
= (0xff0000, 0x0000ff, 0x00ff00);
@folks[0, -1] = @folks[-1, 0];
前述の代入は以下と完全に等価です:
($days[3], $days[4], $days[5]) = qw/Wed Thu Fri/;
($colors{'red'}, $colors{'blue'}, $colors{'green'})
= (0xff0000, 0x0000ff, 0x00ff00);
($folks[0], $folks[-1]) = ($folks[-1], $folks[0]);
スライスを変更すると、スライスした元の配列やハッシュを変更するので、
foreach 構造は配列やハッシュの値の一部 -- あるいは全部 -- を
置き換えます。
foreach (@array[ 4 .. 10 ]) { s/peter/paul/ }
foreach (@hash{qw[key1 key2]}) {
s/^\s+//; # trim leading whitespace
s/\s+$//; # trim trailing whitespace
s/(\w+)/\u\L$1/g; # "titlecase" words
}
空リストのスライスはやはり空リストです。 従って:
@a = ()[1,0]; # @a has no elements
@b = (@a)[0,1]; # @b has no elements
@c = (0,1)[2,3]; # @c has no elements
しかし:
@a = (1)[1,0]; # @a has two elements
@b = (1,undef)[1,0,2]; # @b has three elements
これを使うと、空リストが返ったら終了するループを簡単に書けます:
while ( ($home, $user) = (getpwent)[7,0]) {
printf "%-8s %s\n", $user, $home;
}
この文書で前述したように、リスト代入のスカラ評価は、代入の右側の要素の 数です。 空リストは要素を含まないので、パスワードファイルを読み込み終わると、 結果は 2 ではなく 0 になります。
もし、なぜここでハッシュスライスに '%' ではなく '@' を使うのかについて 混乱するなら、次のように考えてみてください。 かっこの種類(大かっこか中かっこか)は、見ているものが配列かハッシュかを つかさどっています。 一方、配列やハッシュの先頭の記号('$' か '@') は、返ってくるものが単一の 値(スカラ)か、複数の値(リスト)かを示しています。
(型グロブとファイルハンドル)
Perl は 型グロブ と呼ばれる内部型を、シンボルテーブルエントリ全体を
保持するために使っています。
この型グロブの型接頭辞は * です。
なぜなら、それが型全てを表すからです。
これは関数に対してリファレンスを使って配列やハッシュを渡すために
好んで使われていた方法でした。
しかし、私たちは今では本当のリファレンスを持っていますから、
型グロブを使う必要はほとんどありません。
最近の Perl での型グロブの主な用途は、シンボルテーブルのエイリアスを 作るというものです。 具体的には以下のようにします:
*this = *that;
これは $this を $that のエイリアスにし、 @this を $that のエイリアスにし、%this を %that のエイリアスに、 &this を &that のエイリアスにし…のようにします。 より安全にするにはリファレンスを使います。
local *Here::blue = \$There::green;
この例では $Here::blue を一時的に $There::green のエイリアスにしますが、 @Here::blue を $There::blue のエイリアスにはしませんし、 同様に %Here::blue を %There::green のエイリアスにはしません。 これは奇妙に思えるかもしれませんが、これが モジュールのインポート/エクスポートシステムの基盤となっているのです。
型グロブの別の用途には、関数にファイルハンドルを渡したり、 新たなファイルハンドルを生成するというものがあります。 もしファイルハンドルを保存するために型グロブを使う必要があるのなら、 以下のようにします:
$fh = *STDOUT;
あるいは、以下のように本当のリファレンスを使います:
$fh = \*STDOUT;
関数中で間接的にファイルハンドルを使う例については perlsub を 参照してください。
型グロブは local() 演算子を使ったローカルなファイルハンドルを 作成するのにも使われます。 それによって作成されたものはそれを囲むブロックが存在する間だけ 存在しますが、呼び出し元へ返すことが可能です。 例を挙げましょう:
sub newopen {
my $path = shift;
local *FH; # not my!
open (FH, $path) or return undef;
return *FH;
}
$fh = newopen('/etc/passwd');
今では *foo{THING} 表記がありますから、型グロブはファイルハンドルの
操作のために用いられることはそれほどではありませんが、
ファイルハンドルやディレクトリハンドルを関数に対して渡したり、
関数の外へ返すためにはまだ必要となります。
これは *HANDLE{IO} は HANDLE が既にハンドルとして使われた場合にのみ
動作するからです。
言い換えると、*FH は新しいシンボルテーブルのエントリーを作成するために
使わなければなりませんが、*foo{THING} を使うことはできません。
疑わしい場合は、*FH を使ってください。
ファイルハンドルを作成できる全ての関数 (open(),
opendir(), pipe(), socketpair(), sysopen(), socket(), and accept()) は、
もし渡されたハンドルが初期化されていないスカラ変数の場合、
無名ファイルハンドルを作成します。
これにより、open(my $fh, ...) や open(local $fh,...) のような
構文によって、他からのリファレンスがなければスコープの終わりに自動的に
閉じられる便利なファイルハンドルを作ることができます。
これは、以下の例のように、他に渡す必要があるファイルハンドルを開く時に
型グロブを使う必要性を大きく減らします:
sub myopen {
open my $fh, "@_"
or die "Can't open '@_': $!";
return $fh;
}
{
my $f = myopen("</etc/motd");
print <$f>;
# $f implicitly closed here
}
代わりに初期化されたスカラ変数が使われると、結果は異なることに
注意してください。
my $fh='zzz'; open($fh, ...) は open( *{'zzz'}, ...) と等価です。
このような動作を禁止するには use strict 'refs' を使ってください。
無名ファイルハンドルを作るもう一つの方法は Symbol モジュールか IO::Handle モジュールを使用するというものです。 このモジュールは local() を使ったときのように同じ名前を 隠してしまうようなことがないという利点があります。 これを使った例は perlfunc/open() の末尾を参照してください。
Perl の組み込み変数と、有効な変数名に関する議論に関しては、 perlvar を参照してください。 型グロブに関する議論と *foo{THING} 構文に関することは、perlref, perlsub, perlmod/"Symbol Tables" を参照してください。