そろそろPerl4に関して一言いっとくか(クラシカルPerl入門)

仕事でPerlを使うことになり、先週から久々に(本格的に)使ってみました。大体プログラミング言語なんてものは特殊なやつを除けばどれも根本は同じなので、それ自体で詰まるということはありません。
が、10数年ぶりのPerlを使いながら、懐かしいことを思い出してみました。思えば遠くへ来たものだ。

アンパサンド

Perl5以降では当然のようにサブルーチンを hoge() と呼び出しますが、Perl4では &hoge と呼び出します。

my!our!

Perl4では、my*1だとかありませんし、our*2ももちろんありません。
当然ながら、localを使います。

myはまさにレキシカルスコープ、ourはパッケージローカルな変数となります。で、Perl4に存在した(というか、今も存在しますが)localというのは、特殊なグローバル変数。その時点でグローバル変数の値を置き換えてしまい、ブロックを出た後でグローバル変数の値を戻します。つまり、以下では、test2()の中で$aが10ではなく1なのですね。myによる宣言とは意味が異なります。

$a = 10;

sub test {
   local $a = 1;
   test2();
}
sub test2 {
   print $a; # 10 or 1?
}

なお、localを使う意味はほぼ既にありません。

型グロブ

Perlにはグロブというものが二種類あり、一つがファイル名グロブ*3で、もう一つが型グロブです。

型グロブというのは、普通に生きている我々は使わないのですが、特殊な用途で利用します。Perlで使う変数やサブルーチンなどは総称して「シンボル」と呼ばれますが、この「シンボル」を統合して使うのが型グロブです。
何を言っているのかわからないかもしれませんが、簡単に言えば、$a、@a、%a、&aといったものを統合して*aとして指す機能が型グロブです。

それで何ができるのかといえば大したことができるわけではないのですが、Perl4ではたまに用途がありました。その一つが「ファイルハンドルの変数化」です。

ファイルハンドルは、何も考えずに使うとグローバルとなります。

open(FILE, "file.txt");
# このFILEはプログラム全体で参照可能。

これが非常にうざいわけです。例えばローカル化したり、サブルーチンの引数に渡したりしたいわけです。
しかし、このFILEは変数ではありません。

しかし、型グロブ*FILEを使うと、このFILEというファイルハンドルを変数のように使うことができます。

local *FILE; # FILEを局所化
open(FILE, "file.txt");

sub test{
   local(*FILE) = shift; # 変数のように使える。
   while(<FILE>){
      print;
   }
}

なお、仮に$FILEとか@FILEといったものが別個に存在した場合、*FILEによって巻き添えにされますのでご注意。

今なら、ファイルハンドルはモジュール経由で扱うことができます。

フォーマット文

Perl4でどうのという話ではありませんが、昨今のPerlであまり見かけない機能。確か昔は「はじめてのPerl」でも紹介されていた機能です。

$name = "Yamada";
$age = 30;
write REPORT;

format REPORT
|@<<<<<<<<< | @>>|
$name, $age
.

これによって、上で言えば$nameと$ageの内容を|Yamada | 30| のように整形して出力することができます。

なぜ使われないかといえば、formatで参照される変数は、グローバルである必要があるため。(ourやらlocalならば可ですが、myだとダメですね。)なお、formlineって機能がありますが、これも使われているのを見たことないですね。

dbmopen

最近は、ファイルDB(BarkleyDBなど)を直接に扱うことも少ないのかもしれません。が、tie*4を使って、DBとハッシュを結びつけるという手法があります。

ですが、Perl4ではdbmopen()を使います。はじめてのPerlでも使ってましたね。

dbmopen(%MYDB,'dir/dbfile',0666);

こうやって、DBに結びつけたハッシュを使います。ちなみに、閉じるときはdbmclose()があります。

今では使う意味がありません。

シンボリックリファレンス

リファレンスを使うのはPerl5では当然。しかしPerl4にはそのようなしゃれたものはありませんでした。

しかし、こんなことはできます。

$a = "abc";
$abc = "xyz";
print ${$a}; # これが print $abc; として働く

これがシンボリックリファレンス、あるいはソフトリファレンスです。皆様がPerl5で使っているものがハードリファレンス。
既に、使う意味は全くないといえるでしょう。use strict;すると使えませんし。

ハードリファレンスがないということは、矢印演算子もありません。

chop

chomp() によって、行末改行文字を切り取るのはよく使う機能の一つですが、これもPerl5から。Perl4ではchop()を使って、行末の1文字を切り取ります。

map

Perl4にはmap関数もありませんでした…。ですので、配列の置き換えはforeachなどを使っていました。

モジュール

そもそもモジュール自体ありませんでした。ですので、useすることもありません。requireによって他のコードを取り込むことはできました。

CPANからモジュールを引っ張ってきて簡単に機能が増やせるようになったのもPerl5のおかげ。

論理演算子

「かつ」や「または」といったものに、and/or/notを使えるのもPerl5から。Perl4では&&と||と!です。
とはいえ、Perl5でPerl4風の書き方が使われなくなったわけではありません。andと&&は結合の強さが違うので注意(他も同様)。

その他

パッケージ

パッケージはPerl4でもある、のですが、区切り文字は皆様の大好きな「::」ではなく、驚きの「'」(シングルクォート)です。

jcode.pl では &jcode'convert(*line, "euc"); なんて感じで文字コード変換を書いていました*5

プロトタイプ宣言

Perl4ではプロトタイプ宣言もできないわけですが、といって、プロトタイプ宣言ってそんなに使われてないような気もします。

連想配列

そういえば、Perl4では、ハッシュのことを連想配列(associated array)と呼んでいました。まあ、これは呼び名の問題に過ぎません。

正規表現

Perl4には最短マッチも先読みもありません。
その他、機能が大きく拡張されました。

配列の添え字

配列の添え字が負の数のときに後ろから数えてくれるとか?

不毛な争いはなかった

この手の言語は基本的にPerlしかありませんでした。
ですので、「PHP(笑)」とか「そろそろPHPに関して一言いっとくか」とか「ruby >>>>(超えられない壁)>>>> perl」とか「Perl(笑)は過去の言語」なんてことを言っちゃう人はいませんでした。

*1:Perl5で導入。

*2:Perl5.6で導入。

*3:Perl5ではglob関数がありますが、Perl4では普通は<*.txt>のように書いていましたな。

*4:Perl5で登場

*5:ここでも型グロブ! これで$lineを書き換えてもらいます。