Perl 5 と CPAN が作ったもの — 成功しすぎた言語は、変えられなくなる

1994 年、Perl のインタプリタは一から書き直された。リファレンス、モジュール、bless による OO、レキシカルスコープ。翌年には CPAN が作られる。当時どの言語にも存在しなかったものだ。そして Perl 5 は成功しすぎた — 30 年分のモジュールが動き続けるという事実こそが、後に「互換性を切るなら別の言語にするしかない」という結論を用意することになる。

perlcpanhistorylanguage-designpackage-managerprogramming-languages

前回、Perl 4 が 2 つの制約を抱えていたところまで書いた。 データ構造がネストできないことと、名前空間がグローバルしかないこと。 そして、その解き方が「改良」ではなく「一から書き直す」だったことも。

今回はその書き直しと、その翌年に起きたことの話だ。

1994 年 10 月 17 日 — Perl 5.000

インタプリタが全面的に書き直された。文法の追加ではなく実装の再構築であり、 ここで Perl は別の言語になったと言っていい。

入ったものは大きく 4 つある。

リファレンス

\ でスカラ・配列・ハッシュ・サブルーチンへの参照が取れるようになった。

my $data = {
    users => [
        { name => 'alice', tags => ['admin'] },
        { name => 'bob',   tags => [] },
    ],
};

Perl 4 では書けなかったものだ。表現できるデータの形から天井が外れた。

パッケージとモジュール

package による名前空間と、use / require によるロード。

これが意味するのは、ファイル単位で他人のコードを取り込めるようになったということだ。 そしてこれは、この回の後半で扱う CPAN が成立するための前提条件そのものである。

オブジェクト指向 — bless

Perl 5 の OO は、既にある仕組みの組み合わせで実現された。

  • オブジェクト = リファレンス(多くはハッシュリファレンス)に bless でクラス名を貼ったもの
  • クラス = パッケージ
  • メソッド = そのパッケージのサブルーチン
  • 継承 = @ISA 配列
package Point;
sub new {
    my ($class, %args) = @_;
    my $self = { x => $args{x} // 0, y => $args{y} // 0 };
    return bless $self, $class;
}
sub to_string { my $self = shift; "($self->{x}, $self->{y})" }

新しい機構をほとんど足していない。 「既存の部品で OO を作れる」という証明であり、Perl 5 の設計の見事さでもある。

そして同時に、「OO が言語に組み込まれていない」という後年の批判の根拠にもなった。 new は慣習であって言語の機能ではない。属性の宣言方法も決まっていない。 だから流派が乱立した。

Perl 6 が class / has / method を言語に組み込んだのは、ここへの応答である。

レキシカルスコープ — my

my による語彙的変数。それまでの local(動的スコープ)と違い、 ブロックで閉じる変数が書けるようになった。

use strict と組み合わさることで、Perl は「大きなプログラムを書ける言語」になった。

1995 年 10 月 26 日 — CPAN

Comprehensive Perl Archive Network。 Perl のモジュールを集積・配布するアーカイブ網である。

Perl の歴史で、おそらくこれが最も影響の大きい発明だ。 そして言っておきたいのは、当時これに相当するものが、どの言語にも無かったということである。

仕組み 開始
CPAN 1995
PyPI 2003
RubyGems 2004
npm 2010
Cargo(crates.io) 2014

CPAN は 8 年間、他に比較対象が存在しない状態だった。

CPAN が発明したもの

「モジュールを置く場所」だけなら、当時も FTP サイトはあった。CPAN が違ったのは、 周辺の仕組みを最初から持っていたことだ。

1. PAUSE — 作者登録と名前空間の管理

誰が何という名前のモジュールを出せるかを管理する。 名前の衝突を、技術ではなく運用で解いた。

2. メタデータの標準化

依存関係、ライセンス、前提となる Perl のバージョン。 これらを機械可読な形で持つことで、インストーラが自動で依存を解決できる。

3. ミラー網

世界中のミラーによる分散配布。1995 年の回線事情では切実な機能だった。

4. CPAN Testers

これが最も特異だ。多数のプラットフォーム・多数の Perl バージョンで自動的にテストを走らせ、 その結果を公開する仕組みである。

モジュールの作者は、自分が持っていない OS・持っていないバージョンでの結果を見られる。 「私の環境では動く」を、制度として超える仕組みを 1990 年代に作っていた。

現代の CI に相当するものが、パッケージリポジトリの機能として存在していた。 そして興味深いことに、後発のパッケージマネージャはこれを引き継がなかった。 npm にも RubyGems にも、これに相当する公式の仕組みは無い。

CPAN について書くとき、モジュール数で語られることが多い。 しかし発明として重要なのは数ではなく、この 4 つの仕組みを最初から揃えていたことだと思う。

インターネットの粘着テープ

1990 年代後半、Perl は Web の主要言語になった。理由は 3 つある。

1. CGI との相性。 標準入出力と環境変数で完結する仕様は、 テキスト処理言語にとって理想的だった。

2. 文字列処理。 HTTP もHTML もテキストである。Perl の正規表現がそのまま武器になった。

3. mod_perl(1996、Doug MacEachern)。 Apache に Perl インタプリタを埋め込み、プロセス起動のコストを消した。 実質的に最初期のアプリケーションサーバである。

この時期の Perl は「インターネットの粘着テープ(duct tape of the Internet)」と呼ばれた。 Amazon も、初期の Slashdot も、数え切れないサイトが Perl で書かれた。

Perl 5.6(2000 年 3 月)

バージョン番号の表記が 5.005 形式から 5.6.0 形式に変わった。内容面では:

  • Unicode の初期サポート
  • our によるパッケージ変数の宣言
  • 64bit 対応、大きなファイルの扱い

そしてこの 4 か月後に、Perl 6 が発表される。

ここは誤解されやすいので強調しておきたい。 Perl 6 は、Perl が衰退したから始まったのではない。 Perl が Web を支配し、CPAN が唯一無二の資産であり、絶頂にあった時期に構想された。

成功しすぎた言語

ここが、この回でいちばん書きたかったところだ。

Perl 5 の設計判断のうち、後に「変えたいが変えられない」ものになったものがある。

判断 何が問題になったか
シジルが文脈で変わる(@a の要素が $a[0] 初学者が最もつまずく点
OO が bless ベース 標準の書き方が定まらず流派が乱立
関数の引数が @_ シグネチャが書けない
文脈(スカラ/リスト)が暗黙 挙動の予測が難しい

これらは Perl 5 では変えられなかった。後方互換性のためである。

そして後方互換性が重かったのは、まさに CPAN があったからだ。

  • 数万のモジュールが動いている
  • 世界中の本番環境が動いている
  • 30 年分の資産がある

Perl 5 の最大の資産が、Perl 5 を変えられなくしていた。

ここに、この連載を通じて何度も出てくる型がある。

成功した言語は、その成功の形に固定される。 資産が大きいほど、根本的な変更のコストは上がる。

Perl 4 のときは、資産がまだ小さかったので書き直せた。互換性もおおむね保てた。 Perl 5 のときは、それができなかった。

だから 2000 年の判断はこうなる。

根本的に変えたい。しかし Perl 5 は変えられない。 ならば、別の言語を作るしかない。

これが Perl 6 の出発点である。 そして「別の言語なのに Perl 6 という名前を付けた」ことが、 19 年後に名前を変える理由になる。

その 19 年の入口を、次回から見ていく。


次回(第 3 話): 2000 年、Perl 6 が始まった。 Perl 5 Porters の会合で割れたマグカップ、State of the Onion での発表、 そして言語設計を公募したら何が起きたか — 361 本の RFC の話。

← Back to Perl と Raku の系譜