言語設計を成功させるにはどうすればよいのだろう?Unix開発の貢献者のひとりで,Awkの生みの親でもあるBrian Kernighan氏は,ノッティンガム大学で行った講演の中で,この疑問に対して答を出そうと試みている。
講演の中でKernighan氏が取り上げたのは,あるアプリケーションが関係する特定の問題を解決すべく設計された言語,いわゆるドメイン固有言語である。一般的なドメイン固有言語は,狭い適応ドメインを持ち,チューリング完全を必要としない,“小さな”言語である。Kernighan氏がドメイン固有言語に興味を持つのは,C++など他の複雑な言語と比較して,言語設計および言語設計者に対して,はるかに多くの表現上の余地を残してるからだ。成功したドメイン固有言語の例としては,正規表現,シェル,Awk,XML,HTML,SQL,Rなどがある。
言語の提供する表記法(notation)は,言語設計の根幹をなす部分だ。その言語を使うことで,ほとんど何の努力もなく問題を解決できるか,あるいは大変な苦労を強いられるか(他の種類の問題では状況が違うかも知れないが)は,その表記法によって決められる。さらに表記法は,問題に対する考え方にも影響する,とKernighan氏は言う。
Kernighan氏が最初の例として分析したのは,処理方法の指定にパターン-アクションパラダイムを使用するAwkである。このような処理方法の選択は,1行で記述可能なシンプルな言語という,Awkの設計目標によって動機付けられたものだ。長いプログラムを書くという“乱用”も実際には可能だが,Awkが本領を発揮するのは短いプログラムにおいてなのだ。Awkの表記法についてもうひとつの特徴は,C言語のそれに似ていることだ。Kernighan氏によれば,新たに何かを学ばなくてよいという点は,Awkの重要なアドバンテージとなっている。
1行プログラムを重視したことから,型宣言の省略や自動初期化,組込み変数,文字列と数値のどちらも操作可能な演算子,連想配列と正規表現のサポート,制御フロー文,組込み関数などといった,言語の具体的な機能が考案された。
同じように重要なのが,Awkを通じて可能になった教訓の数々だ。まず第1にあげられるのは,ツールが予期しない利用法やミスは必然であって,回避は困難であるという点だ。特に,言語に新たな機能を加える,あるいは具体的な問題に対して修正ないし改良するという行為は,言語の安定性を損なうことになるため,これらを避けることは,Kernighan氏としては基本的な部分である。さらに,新たな表記を追加することは,構文の一貫性を失うことでもある。
Kernighan氏が紹介した第2の例は,変数セットとそれらの値に対する制約をベースとして最適化問題を解決する,代数モデル言語のAMPLである。氏はこの言語を設計した一人であると同時に,最初の実装も自身で行っている。AMPLは宣言的構文を持ち,問題の変数とその制約を記述することができる。さらにデータを記述するための言語や,AMPLの動作をコントロールするコマンド言語も備えている。
AMPLは適度な成功を収めたのは,その機能が少なかったことも一因だ,とKernighan氏は言う。特に重要なのは,問題の領域を具体的に限定したことにより,大学が授業で取り上げたり,業界でいち早く採用されたりした点だ。AMPLの表記法は当初,宣言のみに限られていた。その後,条件分岐やループ,関数などが追加されたことで,言語としてはチューリング完全になったが,同時に,不自然で不規則な構文も加わることになった。AMPLのもうひとつの特徴はクローズドソースであることだ。これが成功の一因であることは間違いないものの,議論の余地のある点のひとつだろう,とKernihan氏は述べている。
Kernighan氏が次にケーススタディとしてあげたのは,Lorinda Cherry氏が1974年に設計した,数学用組版言語のEQNである。EQNの基本となっているアイデアは,言葉で話すように数式を記述することができて,TeXへのインプットとして使用可能な言語を実装する,というものだった。
x sup 2 + y sup 2 = z sup 2
f(t) = 2 pi int sin(omega t) dt
この構文のおかげで,数学者ではない,Bell研究所内のタイピストでもEQNが使えるようになった,とKernighan氏は言う。EQNに関する基本的な設計判断のひとつとして,パイプを使って出力をtroff
に渡している点がある。これは元々,開発された当時のコンピュータのメモリに関する制限からきたものだったが,既存のツールを利用するというのは,実装の複雑さを低く保てるという意味からも,DSLを実装する上で優れたアプローチだ,とKernighan氏は評価している。
Kernighan氏が紹介したもうひとつの組版言語であるPicは,テキストを線画に変換するための言語だ。Picを使用することのメリットには,システム変更の容易さ,サイズの正確性の保証,ループや条件を使用した繰り返し構造の利用,といったものがある。この言語も出力ステージとしてtroff
を使用して,Picプリプロセッサにパイプ入力するアプローチを採用している。言語の実装にはYACCとLEXが使用されているので,新たな構文の実験や,あるいは座標指定への依存度の低い,自由形式の英語風の構文を構築することも簡単にできる。次に示すのは,単純なフローチャートがPicで指定できることの例である。
arrow;
box "input";
arrow;
box "process";
arrow;
box "output";
arrow
これまでにあげた例に基づいて,kernighan氏は次に,これらの言語が成功を収めた理由を説明するための原則をいくつか示した。
- 何よりも表記法によって,これまでよりも明らかによい方法で,現実の問題を解決していること。
- 文化的に馴染みがあって受け入れやすいこと。例えば取り掛かりを容易にするために,多くの言語がC言語風の構文を採用していることなどはこれに当てはまる。
- 既存ツールのエコシステムとの親和性が高く,まったく新しい環境を受け入れたり,標準的なツールを廃止したりする必要がないこと。
- オープンソースであること – 特に最近ではこれが重要だ,とKernighan氏は言う。
- 競合が少なく,運がよいこと。
その一方で,完全に消滅する訳ではないにせよ,その言語が失敗に終わるような要素もいくつか存在する。
troff
をベースとしたKernighan氏の言語のように,消滅するニッチやドメインを対象とした言語であったため。- 巨大すぎる,複雑すぎる,動作が遅過ぎる,あるいは登場した時期が遅過ぎるため。この例として特にあげられるのは,登場するのが間違いなく遅すぎたPerl 6と,大規模かつ複雑になり過ぎたC++の2つだ - ただしC++については,現在も新しい開発で数多く利用されているが。
- 思想に乏しい選択に基づいているため。例えば,機能を犠牲にしてイデオロギ的な選択をする傾向や,“数学的”あるいは“差別化”などの極端な志向は,いずれも潜在的ユーザ数を減らすことになる。
最後にKernighan氏は,新しい言語を生み出すためのインスピレーションあるいはガイドとしても役立ちそうな,Alan Perlis氏の言葉を引用した。曰く,新しいアプローチよりもまず,既にある最高のものを組み合わせて,よりよい結果を得られないかを試すべきだ。
私たちのプログラムの中には,既存のどの言語でも不十分と言うしかない,と言いたくなるようなものが必ず存在するのです。