Perl には、スカラー、スカラーの配列、「ハッシュ」(hash)とも 呼ばれるスカラーの連想配列という 3 つのデータ構造があります。通 常の配列は 0 を基点とする数値で添え字づけされます(負の添字は、配 列の終わりから添え字づけします)。ハッシュ配列は、文字列で添え字づけされます。
値は通常、名前を使って(もしくは名前付きのリファレンスを通して)参 照されます。名前の最初にあるキャラクターは、その名前がどのような構造のデータを参照しているのかを区別します。名前の残りの部分は、参照する値を特定するものです。ほとんどの場合は、名前は一つの識別子
(indentifier)、つまり、文字かアンダースコアから始まってそれに文 字、アンダースコア、数字が続く文字列のことです。一部のケースにおいては::
で分けられた識別子の並びであってもかまいません('
も
使えますが、これはお薦めしません)。これの最後のもの以外の名前は、 最後の部分にある識別子をその名前空間に置くためのパッケージの名前として解釈されます(詳細は
Packagesを参照してください)。 リファレンスを生成する式の単純な識別子を、実行に値に置き換えることも可能です。これはこのドキュメントの後の部分と、the
perlref manpageに詳 細な説明があります。
これらの規則に従っていない名前を持っていて、あなたが使った普通の 変数との間で間違って衝突することがない特殊変数があります。正規表現の括弧づけされた部分(parenthesized
parts)の文字列は$
の後に 数字だけが続いている名前で保存されます(
perlop と perlreを 参照してください)。それに加え、Perlの内部的な動作に対する窓を開
けている幾つかの特殊変数が、句読点キャラクターを含む名前を持っています(perlvarを参照)。
スカラー値の参照は配列の一要素であるスカラーを参照する場合でも、 常に名前に '$' を付けます。以下のようなものが使えます:
$days # 単純なスカラー変数 "days" の値 $days[28] # 配列 @days の 29 番目の要素の値 $days{'Feb'} # ハッシュ %days の 'Feb' の値 $#days # 配列 @days の最後のインデクス値
ただし、配列全体や配列のスライスは '@' で示します:
@days # ($days[0], $days[1],... $days[n]) @days[3,4,5] # @days[3..5] と同じ @days{'a','c'} # ($days{'a'},$days{'c'}) と同じ
ハッシュ全体は '%' で示します:
%days # (key1, val1, key2, val2 ...)
さらに、サブルーチンは名前の前に '&' を付けて示しますが、曖昧に ならなければ、(英語でもほとんど使われなくなった ``do'' のように) 省略することができます。シンボルテーブルのエントリは、名前に '*' を付けて示すことができますが、使用に際しては十分に注意する必要があります。
変数のすべての型には、それぞれの名前空間があります。衝突を心配せ ずに、スカラー変数、配列、ハッシュ
(ついでにファイルハンドルやサブルーチン名、ラベル) に、同じ名前を付けることができます。つまり、
$foo
と @foo
は 2 つの異なる変数であるということです。また、
$foo[1]
は @foo
の一部であって、$foo
の一部ではありませ ん。奇妙に思えるかもしれませんが、それで良いのです。奇妙なのですから。
変数と配列の参照は、いつも '$'、'@'、'%' で始まりますから、「予 約」語は、変数名としては、本当の意味で予約されているわけではありません。(しかしながら、先頭に特別な文字を付けない、ラベルやファイ
ルハンドルとしては、予約されていることになりま す。たとえば、``log'' といった名前のファイルハンドルを使うこ
とはできません。ヒント: open(log,'logfile')
などではなく、
open(LOG,'logfile')
としてください。大文字のファイルハンド
ルを使えば、読みやすくもなりますし、将来に渡る予約語との衝突も避けられます。)大文字と小文字は区別されますから、``FOO''、
``Foo''、``foo'' は、すべて違う名前です。英字と下線で始まる名前は、名前の一部に数字やアンダースコアを含むことができます。
そのような英数字の名前を、その型のオブジェクトへのリファレンスを返す式で置き換えることも可能です。詳しくは、the perlref manpage を参照してください。
数字で始まる名前には、数字しか含めることができません。英字、下線、数字以外の文字で始まる名前は、$%
や $$
のように 1 文字に限定されます(これら 一文字の名前の多くは、Perl
があらかじめ意味を定めています。たとえば、$$
はカレントプロ
セスのプロセス id を示します)。
Perl における演算や値の解釈は、その演算や値の置かれたコンテ キストからの要求に依存する場合があります。このコンテキストというものには大きく二つあり、スカラーコンテキストとリストコ ンテキストと呼ばれます。リストが要求されるコンテキストではリスト値を返し、そうでなければスカラー値を返すような演算も存在 します。(そのような演算については、ドキュメントでその演算に触れるときに付記しています。)言い方を変えると、Perl では、 ある種の演算が一つの値を返して欲しいか、複数の値を返して欲しいかによって多重定義されているということです。(``fish'' や ``sheep'' といった、単複同形の英単語と似ているかもしれません。)
逆に演算子は、その引数がスカラーコンテキストかリストコンテキストのいずれかで解釈されるかを決めてしまいます。たとえば、
int( <STDIN> )
と書くと、int 演算子は、自分の引数である <STDIN> 演算子 がスカラーコンテキストで評価されることを期待するため、<STDIN> はSTDIN から一行を読み出して int 演算子に渡します。int 演算子は 、その行から整数値を取り出して返すことになります。これに対して、もし
sort( <STDIN> )
と書いたなら、sort 演算子は <STDIN> 演算子がリストコンテ キストで評価されるために 、<STDIN> は STDIN から読める限 り最後の行まで読み出して、そのリストを sort のルーチンに渡します。 sort ルーチンは受け取った行のリストをソートし、その結果のリストが戻り値となります。
代入演算は少し特殊です。代入では、右引数のコンテキストを決 めるために左引数が使われます。スカラーへの代入では、右側をスカラコンテキストで評価しますが、配列や配列のスライスに対する 代入では、右側をリストコンテキストで評価することになります。リストへの代入も、右側をリストコンテキストで評価することになり ます。
ユーザが定義するサブルーチンは、自分がスカラーコンテキストで 呼ばれたか、リストコンテキストで呼ばれたかを意識することができますが、多くのサブルーチンでは意識する必要もないでしょう。スカラー値は自動的にリストの要素になることができるからです。 perlfuncを参照してください。
Perlにおける全てのデータは、スカラーであるか、スカラーの配列、ス カラーのハッシュとなります。スカラー変数は、数値、文字列、リファレンスのような単純な種類のデータを保持することができます。一般的 には、ある種類から他の種類への変換は透過的(transparent)です(スカラーは複数の値を保持することはできませんが、複数の値を保持してい る配列やハッシュに対するリファレンスを保持することができます)。これは、スカラー、操作、スカラーを返す関数の自動変換はそのコンテ キストが文字列を対象としているのか数値を対象にしているのかを気にする必要がない(実際は、気にすることができません)ためです。
スカラーは何かであることを宣言する必要はありません。あるスカラー 変数が、“文字列”型、“数値”型、“ファイルハンドル”型、あるいはその他の型であるように宣言する方法はありません。Perlは文字列、 数値、リファレンス (オブジェクトを含みます)を保持することのできるスカラーを持つ文脈的な多態言語(contextually polymorphic language) です。文字列と数値は、ほとんど全ての目的に対して適当であるように 思われるものの、リファレンスは組み込みのリファレンスカウントとデストラクターとを持っている、キャストすることのできない強く型づけ (strongly-typed)されたポインターです。
スカラー値は、その値が空文字列か数値の 0 (あるいは同値な文字列``0'') 以外の場合には、ブール値の真として扱われます。ブール値が必要となるコンテキストは、単に特別なスカラーコンテキストとして扱われます。
スカラーのナルには、実は defined と undefined の ニ種類がありま す。undefined
のナルは、エラーがあったときや、ファイルの終わりに 達したとき、初期化していない変数や配列要素を参照したときなど、何かに対する実際の値が存在しないときに返されます。undefined
のナル は、最初に defined であるかのように使ったときに defined となり得
ますが、それに先立って値が definedであるかどうかを調べるために defined()
演算子を使うことができます。
与えられた文字列が正当な非ゼロの数値であるかどうかを確かめるには、 数値の 0 か lexical な ``0''に対してテストすれば通常は十分です(も っともこれは-wでノイズを引き起こします)。数値ではない文字列は、 awkのように0とはみなすことはしないからです:
if ($str == 0 && $str ne "0") { warn "That doesn't look like a number"; }
これは通常の場合は好ましいものです。なぜなら、あなたがIEEE記法の NaN
やInfinity
のような属性を扱わないだろうからです。その他
にも、データが数値であるかどうかを検査するために正規表現を使うのは好ましいかもしれません。正規表現の詳細についてはperlreを参
照してください。
warn "has nondigits" if /\D/; warn "not a whole number" unless /^\d+$/; warn "not an integer" unless /^[+-]?\d+$/ warn "not a decimal number" unless /^[+-]?\d+\.?\d*$/ warn "not a C float" unless /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/;
配列の大きさはスカラー値です。配列 @days
の大きさは、csh のよう
に $#days を評価するとわかります(実際は、これは大きさではなく、 最後の要素に対する添え字になります。(通常は)0
番目の要素があるか らです)。$#days に代入を行なうと配列の大きさも変化します。この
方法で配列を小さくすると、見えなくなった部分の値は破壊されます。小さくした配列を再び大きくしても、以前存在した要素に対する前の値
が回復することはありません(Perl 4 では回復可能でしたが、デストラクターが期待通りの時点で呼ばれることを保証するために、これを止め
ました)。大きくなるであろう配列をあらかじめ大きくしておくことで、ある程度の効率を得ることもできます(最後の要素よりも後ろに離
れた位置に代入を行なうことでも、配列を大きくすることができます)。 配列に空リスト
() を代入すると、何も無い状態にまで切り詰めることができます。以下の二つは等価です:
@whatever = (); $#whatever = -1;
名前のある配列をスカラーコンテキストで評価すると、配列の大きさが 返されます(これは、リストに対しては成り立ちません。この場合には、 C のカンマ演算子と同じく最後の値が返されます)。以下は常に真とな ります:
scalar(@whatever) == $#whatever - $[ + 1;
Perl version 5 では $[
の意味を変更しました。$[
を設定して いないファイルにおいて、他のファイルがこの変数を変更しているかどうかを心配する必要がなくなりました(言い換えると、$[
は使わな いほうが良いと言うことです)。ですから、普通は以下のようになります。
scalar(@whatever) == $#whatever + 1;
一部のプログラマーは、曖昧さをないので陽に変換することを選ぶでし ょう:
$element_count = scalar(@whatever);
ハッシュをスカラーコンテキストで評価した場合、ハッシュの中に一つ つでも key/value のペアが登録されているときにだけ、真となる値が返されます(key/value のペアが登録されていれば、返される値は使 用しているエントリの数と、割り付けられているエントリの数を、スラッシュで区切った文字列です。これは、与えたデータに対して、Perlの (コンパイルされた) ハッシュのアルゴリズムが、うまく動作しないかを確認するときくらいにしか使えませんが。たとえば、ハッシュに 10,000 のものを入れ、%HASH をスカラーコンテキストで評価したとき に ``1/16'' が得られれば、16 のうち一つのエントリだけが使われ、お そらくそこに 10,000 すべてが入っていることを意味します。ほとんど起こりそうもないことですが)。
数値リテラルは、慣習的な浮動小数点数と整数の形式で示されます:
12345 12345.67 .23E-10 0xffff # 十六進数 0377 # 八進数 4_294_967_296 # アンダースコアは読みやすさのため
文字列リテラルは、シングルクォートかダブルクォートで区切られます 。これらは、シェルのクォートと同じように扱われ、ダブルクォートの文字列リテラルでは、バックスラッシュの置換と変数の置換が行なわれ、シングルクォートの文字列では、(``\'
''
と ``\\
''を除いて)これら の置換は行なわれません。普通の UNIX
でのバックスラッシュの置換規則は、改行やタブを始め、ある種の変わった形式のためにも使われます。
一覧はperlopをみてください。
文字列リテラルの中で('0xffff'のように)八進もしくは十六進で表現さ れたものは、その値が表すものに自動的に変換されることはありません。
hex()やoct()といった関数がそのための変換を行います。詳しくは
perlfunc と perlfuncを参照してください。
また、文字列に直接、改行を埋め込むこともできます。つまり、文字列 は、開始した行で終了する必要はないと言うことです。これは素晴らしいのですが、終了のクォートを付け忘れた場合には、次にクォート文字 が見つかるまでの間、Perl はエラーを見つけることができなくなります。それは、スクリプト上でずっと先になるかもしれません。文字列中での 変数の置換は、スカラー変数と配列と配列のスライスに限定されています(言い換えれば、$ や@ で始まる識別子か、それにブラケットで括っ た添え字をつけたものです)。次のプログラムは ``The price is $100.'' と印字します。
$Price = '$100'; # 置換されない print "The price is $Price.\n"; # 置換される
いくつかのシェルと同じように、識別子の前後にカーリーブレースを入 れて、つながっている英数字から切り離すことができます。実際には、そのようなカーリーブレースの内側にある識別子は、ハッシュの添え字にある識別子と同様、強制的に文字列になります。先の例にあった
$days{'Feb'}
は
$days{Feb}
のように書くことができます。
そして、自動的にクォートが仮定されます。しかし、添え字により複雑な何かを使っている場合には式として解釈されます。
シングルクォート文字列は、その前の単語とスペースで区切られていな ければならないということに注意してください。なぜなら、シングルクォートは(使わないことが推奨されていますが) 識別子を構成する文字 として有効なものだからです (Packagesを参照してくださ い)。
__FILE__, __LINE__, __PACKAGE__という三つの特殊なリテラルがあります。これらはそれぞれ、カレントのファイル名、行番号、パッケージ
名を表わします。これらは独立したトークンとしてのみ用いられ、文字列中に展開されることはありません。カレントパッケージが存在しない
場合(package;
とすることによる)、__PACKAGE__は未定義値となりま
す。
__LINE__ と __FILE__ という 2 つの特別なリテラルがあって、プログラムのその時点での行番号とファイル名を示します。これらは、独立し たトークンとしてだけ使用することができ、文字列の中に展開することはできません。さらに、トークン __END__ は、スクリプトを納めたフ ァイルの実際の最後よりも前で、論理的にスクリプトが終わるとき、その位置を示すのに使うことができます。それ以降のテキストは無視され ますが、DATA というファイルハンドルを通して読むことができます(ファイルハンドル DATA は、main のスクリプトからだけ読むことができ、 require されたファイルや eval された文字列からは読めません)。コ ントロール文字 ^D と ^Z を __END__ の同義語として使うことができます。
__END__および__DATA__というトークンは、実際のファイルの終端より 前にある論理的なスクリプトの終端を示すために使うことができます。これらの後にあるテキストは無視されますが、ファイルハンドル DATA を通して読み出すことができます。__END__に対してはmain::DATA、 __DATA__に対してはPACKNAME::DATA(ここでPACKNAMEはカレントのパッ ケージ名です)を使います。^D と ^Zという二つのコントロールキャラ クターは、__END__(もしくはモジュールにおける__DATA_)の同義語です。 __DATA__の詳細とそれをつかった例はSelfLoaderを参照してくださ い。BEGINブロックでは、ファイルハンドル DATAから読み出せないことに注意してください。BEGINブロックはそれが見つかった時点で即実行 されるので、__DATA__(や__END__)トークンがどこにあるのかがわからないのです。
文法的に別の解釈ができない単語は、クォート文字列であるかのように 扱われます。これは“裸の単語”(barewords)と言われます。ファイルハンドルやラベルと同様に、小文字だけからなる裸の単語は将来、予約語とぶつかる危険があります。そのような単語があった場合、-w ス イッチをつけることでPerl がそのような単語を指摘してくれます。裸の単語をなくして欲しいという方もいらっしゃいます。もし、
use strict 'subs';
と書いておけば、サブルーチンコールと解釈できない裸の単語がコンパ イル時にエラーとなります。この制約は囲っているブロックの終わりまで有効です。内側のブロックで
no strict 'subs'
と書くことで、こ の機能を撤回することもできます。
配列変数は、ダブルクォート文字列中で、配列のすべての要素を変数 <$``>
(Englishでは $LIST_SEPARATOR
) 中に示す区切り文字(デフォ ルトはスペース)
でつなげて展開されます。以下は同値です:
$temp = join($",@ARGV); system "echo $temp";
system "echo @ARGV";
検索パターン (ここでも、ダブルクォートのような置換が行なわれます) の中では、解釈する上で曖昧となる場合ができてきます。/$foo[bar]/
は、C>/${foo}[bar]/> と解釈される (この場合 [bar]
は、正規表現
の文字クラス) のでしょうか? /${foo[bar]}/
と解釈される (この
場合 [bar]
は、配列 @foo
の添え字) のでしょうか?
@foo
が他に存在しない場合には、明らかに文字クラスとなります。@foo
が存在す れば、Perl が [bar]
の意味に見当をつけますが、たいてい正しい
解釈をします。もし見当があたっていないときや偏執的にこだわりたい時には、上に書いたようにカーリーブレースを付けて強制的に解釈のしかたを決めることができます。
行指向形式のクォートは、シェルの「ヒアドキュメント」構文をもとにしています。
<<
の後にクォートされるものを終了する文 字列を示し、現在行の次の行からその終了文字列に一致する行の前の行までが、その項目の値となります。終了文字列には、識別子(単語)
か クォートされたテキストが許されます。クォートされている場合には、そのクォート文字の種類によって、実際にクォートされるテキストの扱
いが、通常のクォートと同様にして決められます。クォートされていない識別子とした場合には、ダブルクォートのように扱われます。<<
と識別子の間にスペースを入れてはいけません(もしスペースを入れる と、空識別子として扱われ、最初の空行にマッチするようになります。
下記の MerryChristmas の例を参照してください)。終了文字列は、そ の終了を示す行に単独で
(クォートもしないで、前後に空白を入れることも無く) 置かなければなりません。
print <<EOF; The price is $Price. EOF
print <<"EOF"; # これも同じ The price is $Price. EOF
print <<`EOC`; # コマンドを実行する echo hi there echo lo there EOC
print <<"foo", <<"bar"; # スタックすることも可能 I said foo. foo I said bar. bar
myfunc(<<"THIS", 23, <<'THAT'); Here's a line or two. THIS and here's another. THAT
文を終了するためのセミコロンを付けなければいけないことは、忘れな いでください。以下のようにしたいのではないと言うことをPerl が知ることはできないのですから:
print <<ABC 179231 ABC + 20;
リスト値は、個々の値をコンマで区切って (必要に応じて括弧で括って) 示されます:
(LIST)
リスト値が要求されていないコンテキストでは、リストリテラルの値と しては、C のコンマ演算子の場合のように、最後の要素の値が使われます。たとえば、
@foo = ('cc', '-E', $bar);
は、リスト値全体を配列 foo に代入しますが、
$foo = ('cc', '-E', $bar);
は、変数 bar の値を変数 foo に代入します。本物の配列がスカラーコ ンテキストで評価されたときの値は、その配列の大きさとなります。以下の例では、$foo に 3 という値が代入されます:
@foo = ('cc', '-E', $bar); $foo = @foo; # $foo は 3 となる
リストリテラルの閉じ括弧の前には余分にコンマを置いてかまいません ので、
@foo = ( 1, 2, 3, );
と書くことができます。
リストの中にリストがある場合には、自動的に展開されてしまいます。 これは、外側のリストが評価されると、リストの個々の要素がリストコンテキストで評価され、その結果のリスト値の個々の値が、元のリスト の要素であるかのように展開されるのです。つまり、リストの中では配列も、その性質が現れてきません。
(@foo,@bar,&SomeSub)
というリストは、@foo のすべての要素の後に @bar
のすべての要素を
続け、その後に SomeSub というサブルーチンが返すすべての要素を続 けたものを要素として持ちます。展開されないリストのリファレン
スを作るためには、the perlref manpageを参照してください。
空リストは () で表わされます。リスト中で空リストを展開しても何も 起こりません。つまり、 ((),(),()) は () と等価です。同様に、要素のない配列を展開することは、その場所に何も展開しなかったのと同じことになります。
リスト値にも通常の配列と同じように、添え字をつけることができます。 リストには、曖昧さをなくすために、括弧を付けなくてはなりません。例:
# Stat はリスト値を返す $time = (stat($file))[8];
# SYNTAX ERROR HERE. $time = stat($file)[8]; # おおっと、括弧を忘れた
# 十六進数字を探す $hexdigit = ('a','b','c','d','e','f')[$digit-10];
# “逆カンマ演算子” return (pop(@foo),pop(@foo))[0];
リストにundef
を代入することもできます。これは関数の戻り値の一
部を捨て去るのに便利です:
($dev, $ino, undef, undef, $uid, $gid) = stat($file);
リストを構成する個々の要素すべてに代入が許される場合には、全体のリストに代入を行なうことができます:
($a, $b, $c) = (1, 2, 3);
($map{'red'}, $map{'blue'}, $map{'green'}) = (0x00f, 0x0f0, 0xf00);
スカラーコンテキスト中の配列代入は、代入の右辺にある式によって生成された要素の数を返します:
$x = (($foo,$bar) = (3,2,1)); # $xに2ではなく3をセットします $x = (($foo,$bar) = f()); # $x に f()の戻り値の数をセットします
これはブールコンテキストでリストの代入をしたいときには非常に便利 です。なぜなら、ほとんどのリスト関数は終了時に空リストを返すからです。これは代入が0を生成したときには、それがFALSEと解釈されます。
リストの最後の要素は、配列やハッシュでもかまいません:
($a, $b, @rest) = split; local($a, $b, %rest) = @_;
実際は、リストの任意の要素として配列を使うことができますが、リス ト中の最初の配列が、右辺の値をすべて取り込んでしまうため、それ以降のものはヌルしか受け取ることができません。これは、local()
や my()
では有用かもしれません。
ハッシュリテラルは key と value と解釈される値のペアで構成されま す:
# 上記の map の代入と同じ %map = ('red',0x00f,'blue',0x0f0,'green',0xf00);
通常、リテラルリストと名前付きの配列は互いに交換可能ですが、ハッ シュの場合はそうではありません。通常の配列がハッシュとしてリスト値で添え字づけできないのと同じ様に、リスト値を使って添え字づけす ることはできません。同様に、その一部として別のリストを含むハッシュ(パラメーターリストや関数の戻り値リストを含みます)は常に平坦な key/value ペアにされます。これはリファレンスをきちんと使う理由です。
key/value のペアの間に =>
演算子を使うと読みやすくなりま
す。=>
演算子は実質、見た目に判別しやすいカンマ演算子であ
りますが、その左側にあるオペランドが正当な識別子であるような barewordであるときに、それを文字列として解釈するようになっています。これは、ハッシュの初期化を格好よいものにします:
%map = ( red => 0x00f, blue => 0x0f0, green => 0xf00, );
あるいは、レコードとして使うハッシュリファレンスを初期化するために使います:
$rec = { witch => 'Mable the Merciless', cat => 'Fluffy the Ferocious', date => '10/31/1776', };
複雑な関数のために call-by-named-parameter を使うためにも使えま す:
$field = $query->radio_group( name => 'group_name', values => ['eenie','meenie','minie'], default => 'meenie', linebreak => 'true', labels => \%labels );
ハッシュでは順番に意味がないので、初期化の順序にも意味はないということに注意してください。出力の順序を変える方法の例は、 perlfuncを参照してください。
Perlは typeglob と呼ばれる内部型を、シンボルテーブルエントリー全体を保持するために使っています。この型グロブの型前置は*
で
す。なぜなら、それが型全てを表すからです。これは関数に対してリフ ァレンスを使って配列やハッシュを渡すために好んで使われていた方法でした。しかし、私たちは今では本当のリファレンスを持っていますか
ら、これはほとんど使われなくなりました。これはまた関数にファイルハンドルを渡すために好んで使われていた方法ですが、現在では、
*foo{THING} 記法があるのでこれまた使う必要はほとんどありません。これは、関数に新しいファイルハンドルを渡すためにはまだ必要です
(*HANDLE{IO} は HANDLEがすでに使われたときのみ働きます)。
ファイルハンドルを保存するために 型グロブを使う必要があるのであれば、以下のようにします。
$fh = *STDOUT;
あるいは、以下のように本当のリファレンスを使います:
$fh = \*STDOUT;
以下の例は、ローカルなファイルハンドルを作成するための方法です:
sub newopen { my $path = shift; local *FH; # not my! open (FH, $path) || return undef; return *FH; } $fh = newopen('/etc/passwd');
ローカルなファイルハンドルを作り出すもう一つの方法は、IO::Handle を使って同様のことを行うことです。perlfuncの最後の部分 を参照してください。