言語設計についての5つの質問
Original2001年5月
(これは、2001年5月10日にMITで開催されたプログラミング言語設計に関するパネルディスカッションのためにメモしたものです。)
1. プログラミング言語は人のためのものです。
プログラミング言語は、人がコンピューターに話しかける方法です。コンピューターは曖昧でない言語であれば、どんな言語でも幸せに話すことができます。高水準の言語が存在するのは、人がマシン語を扱えないからです。プログラミング言語の目的は、私たちの脆弱な人間の脳が大量の細部に圧倒されるのを防ぐことです。
建築家は、ある種の設計問題がより個人的であることを知っています。最も清潔で抽象的な設計問題の1つは橋梁設計です。そこでの仕事は主に、与えられた距離を最小限の材料で架橋することです。スペクトラムの反対側は椅子の設計です。椅子デザイナーは人間の尻について考える時間を費やさなければなりません。
ソフトウェアも同様に変化します。ネットワークを通るデータのルーティングアルゴリズムを設計することは、橋梁設計のように素晴らしい抽象的な問題です。一方、プログラミング言語の設計は椅子の設計のようなものです。つまり、人間の弱点に対処することが全てなのです。
ほとんどの人はこれを認めたくありません。数学的な優雅さを持つシステムを設計することの方が、人間の弱点に迎合するよりも魅力的に聞こえます。そして、ある種の優雅さは確かにプログラムを理解しやすくします。しかし、優雅さは目的そのものではありません。
私が言語は人間の弱点に合わせて設計されるべきだと言うとき、それは言語が下手な programmer のために設計されるべきだということではありません。実際、私は最高の programmer のために設計すべきだと思いますが、最高の programmer でさえ限界があります。変数がすべてx[整数]のような言語で programming をしたいと思う人はいないでしょう。
2. 自分や友人のために設計する。
プログラミング言語の歴史を見ると、最高のものの多くは言語の作者自身が使うために設計されたものであり、最悪のものの多くは他人のために設計されたものです。
他人のために言語を設計する場合、常に特定のグループ、つまり言語デザイナーよりも賢くない人々を対象にしています。そのため、あなたを馬鹿扱いする言語になります。Cobolがその最極端な例ですが、多くの言語にはこの精神が染み付いています。
これは言語の抽象度とは何も関係ありません。Cは比較的低レベルですが、作者が使うために設計されたので、ハッカーに好まれています。
下手な programmer のための言語を設計する論拠は、下手な programmer の方が上手な programmer よりも多いということです。それは事実かもしれません。しかし、その少数の優秀な programmer が、ソフトウェアの大部分を書いているのです。
私が興味があるのは、最高のハッカーが気に入る言語をどのように設計するかという問題です。これは、良いプログラミング言語をどのように設計するかという問題と同じだと私は考えていますが、そうでなくても、少なくとも興味深い問題だと思います。
3. プログラマーにできるだけ多くの制御権を与える。
多くの言語(特に他人のために設計されたもの)は、お姉さん的な態度を取っています。つまり、良くないと思うことをするのを防ごうとします。私は逆のアプローチ、つまりプログラマーにできるだけ多くの制御権を与えるのが好きです。
Lispを初めて学んだときに、私が最も気に入ったのは、それが私を対等なパートナーとみなしていたことでした。それまでに学んだ他の言語では、言語とそれを使って書いたプログラムが非常に分離されていました。しかし、Lispでは、私が書いた関数やマクロは、言語自体を構成するものと同じでした。私は言語を書き換えることさえできたのです。これはオープンソースソフトウェアと同じような魅力がありました。
4. 簡潔さを目指す。
簡潔さは過小評価され、時には軽蔑さえされています。しかし、ハッカーの心の奥底を見れば、彼らがそれを本当に愛していることがわかります。APLで驚くべきことを数行のコードで行えると、ハッカーが語るのを何度も聞いたことがありませんか?私は、本当に賢明な人々が本当に好きなものは注目に値すると思います。
プログラムをできるだけ短くするためのあらゆることが良いと思います。ライブラリ関数を多数用意すること、暗黙的にできることは暗黙的にすること、構文を極端に簡潔にすること、さらには物事の名前を短くすることさえも。
短くすべきなのはプログラムだけではありません。マニュアルも薄くすべきです。マニュアルの大部分は、明確化、留保、警告、特殊ケースで占められています。マニュアルを短くするよう強制すれば、最良の場合、言語の中の問題を修正することで実現できます。
5. ハッキングとは何かを認める。
多くの人は、ハッキングが数学、あるいは少なくとも自然科学のようなものであることを願っています。しかし、私はハッキングは建築に more 似ていると思います。建築は物理学に関連していますが、建築家の実際の目的は素晴らしい建物を作ることであって、静力学について発見をすることではありません。
ハッカーが好きなのは、素晴らしいプログラムを作ることです。そして、少なくとも自分の心の中では、研究論文に簡単に変換できない仕事であっても、素晴らしいプログラムを設計することは賞賛に値する営みだと覚えておく必要があります。知的には、プログラマーが愛するような言語を設計することは、論文に掲載できるようなひどい言語を設計することと同じくらい価値があるのです。
1. 大規模なライブラリをどのように整理するか?
ライブラリはプログラミング言語の重要な構成要素になりつつあります。また、それらは大規模化しており、これは危険です。あなたが欲しい機能を持つライブラリ関数を見つけるのに、自分で書くよりも時間がかかるようでは、すべてのコードは単にマニュアルを分厚くするだけです(Symbolicsのマニュアルがその典型例です)。したがって、ライブラリの整理方法に取り組む必要があると思います。理想は、プログラマーが適切な ライブラリ呼び出しを推測できるように設計することです。
2. 人々は前置記法を本当に恐れているのか?
これは私が何年も考え続けてきた問題で、まだ答えがわかりません。前置き記法は私にとってはとてもナチュラルに感じられますが、数学の場合を除いては、です。しかし、Lispの不人気の大部分は単に馴染みのない構文のためかもしれません。それが真実であれば、何か対策をとるべきかどうかは別の問題です。
3. サーバーベースのソフトウェアに必要なものは何ですか?
今後20年間で書かれる最も刺激的な新しいアプリケーションの多くは、Webベースのアプリケーション、つまりサーバー上に存在し、Webブラウザを通じてあなたとやりとりするプログラムになると思います。そしてこのようなプログラムを書くためには、いくつかの新しいものが必要かもしれません。
1つ必要なのは、サーバーベースのアプリが公開される新しい方法に対するサポートです。デスクトップソフトウェアのように年に1、2回の大きなリリースではなく、1日に5、10回もの小さな変更を繰り返すことになります。そして通常、誰もが常に最新バージョンを使うことになります。
プログラムをデバッグしやすいように設計する方法があるのと同じように、サーバーベースのソフトウェアも変更しやすいように設計する必要があります。簡単に変更できるようにする必要があり、あるいは少しの変更と大きな変更の違いがわかるようにする必要があります。
サーバーベースのソフトウェアにとって意外に役立つかもしれないのが継続です。Webベースのソフトウェアでは、継続渡しスタイルのようなものを使って、Webセッションの本質的な無状態の世界の中でサブルーチンの効果を得ることができます。コストがかからなければ、実際の継続を持つのも価値があるかもしれません。
4. 発見されていない新しい抽象化はありますか?
これが現実的な期待かどうかはわかりませんが、私が本当にしたいことの1つは、新しい抽象化を発見することです。つまり、ファーストクラス関数やリカーシブ、あるいはキーワードパラメータほどの違いを生み出すようなものです。これは不可能な夢かもしれません。このようなものは滅多に発見されることはありません。しかし、私はいつも探し続けています。
1. 使いたい言語を使えます。
アプリケーションプログラムを書くということは、デスクトップソフトウェアを書くことを意味していました。そしてデスクトップソフトウェアでは、オペレーティングシステムと同じ言語でアプリケーションを書くことに大きな偏りがありました。そのため10年前は、ソフトウェアを書くということは、Cで書くことを意味していました。やがて、アプリケーションプログラムは珍しい言語で書いてはいけないという伝統が生まれました。そしてこの伝統は長い間育まれてきたため、マネージャーやベンチャーキャピタリストなどの非技術者も、この考えを学んでしまいました。
サーバーベースのソフトウェアはこのモデル全体を一掃してしまいます。サーバーベースのソフトウェアであれば、好きな言語を使えます。この事実をほとんどの人が理解していません(特にマネージャーやベンチャーキャピタリストは)。ハッカーの一部が理解しているからこそ、PerlやPythonといった新しい独立系の言語について聞くことができるのです。PerlやPythonが使われているのはWindowsアプリを書いているからではありません。
これは、プログラミング言語の設計に興味のある私たちにとって、私たちの仕事に実際の聴衆が存在する可能性があることを意味しています。
2. 速度はプロファイラから来る。
言語設計者、あるいは少なくとも言語実装者は、高速なコードを生成するコンパイラを書きたがります。しかし、これがユーザーにとって言語を速くするものではないと思います。Knuthが長い前に指摘したように、速度は重要なボトルネックでしか問題にならないのです。そして誰もが試してわかることですが、これらのボトルネックを予測するのは不可能です。プロファイラが答えです。
言語設計者は間違った問題を解決しようとしています。ユーザーに必要なのは、ベンチマークを走らせて速いことではありません。必要なのは、自分のプログラムのどの部分を書き換える必要があるかを示してくれる言語なのです。実践的な速度はそこから来るのです。だから言語実装者が、コンパイラの最適化に費やす時間の半分を、良いプロファイラを書くことに費やしたほうが、トータルで得になるかもしれません。
3. 言語の設計にはアプリケーションが必要。
これは絶対の掟ではないかもしれませんが、最高の言語はすべて、自分で書いていたアプリケーションと一緒に進化してきたように思います。Cは、システムプログラミングの必要性から生まれました。Lispは記号微分を行うために部分的に開発されたもので、Mccarthyはそれに夢中だったので、1960年の最初の論文の中でも微分プログラムを書いていました。
特に、あなたのアプリケーションが新しい問題を解決するものであれば、言語にも新しい機能が必要とされるようになり、良い影響があります。私個人としては、サーバーベースのアプリケーションを書くのに適した言語を作りたいと考えています。
[パネルの際、Guy Steeleもこの点を指摘し、言語がコンパイラを書くためのものである場合を除いて、アプリケーションがコンパイラ以外のものであるべきだと提案しました。]
4. 言語は使い捨てプログラムを書くのに適している必要がある。
使い捨てプログラムとは、ある限定された課題のために素早く書くプログラムのことです。大きな本格的なプログラムの多くが、最初は使い捨てプログラムとして始まっていたのではないかと思います。ほとんどのプログラムが、使い捨てプログラムから始まっているのではないかと思います。だから、一般的なソフトウェア開発に適した言語であるためには、使い捨てプログラムを書くのに適している必要があるのです。それは、ほとんどのソフトウェアの幼虫期だからです。
5. 構文は意味論と関係している。
構文と意味論は完全に別のものだと考えるのが伝統的です。しかし、これは驚くべきことですが、そうではないかもしれません。私が欲しいと思う言語の特徴は、それを表現する方法と関係しているかもしれません。
最近、Robert Morrisと話をしていて、演算子オーバーロードは中置構文の言語で大きな利点になると指摘されました。前置構文の言語では、定義した関数はすべて演算子として機能します。新しい数値型の足し算を定義したい場合、新しい関数を定義するだけで済みます。中置構文の言語でそれをする場合、演算子オーバーロードの使用と関数呼び出しの見た目が大きく異なります。
1. 新しいプログラミング言語。
1970年代は新しいプログラミング言語を設計するのが流行りでした。最近はそうではありません。しかし、サーバーベースのソフトウェアによって、新しい言語が再び流行するようになると思います。サーバーベースのソフトウェアであれば、好きな言語を使えるので、他にある言語よりも優れた言語が設計されれば、それを使うリスクを取る人が出てくるでしょう。
2. タイムシェアリング。
リチャード・ケルシーは最後のパネルでこれがもう一度時期が来た考えを述べ、私もそれに完全に同意します。 私の推測(そしてマイクロソフトの推測のようです)は、多くのコンピューティングがデスクトップからリモートサーバーに移行するということです。つまり、タイムシェアリングが復活するのです。そして、これをサポートするためには言語レベルでの支援が必要になると思います。例えば、リチャードとジョナサン・リースが Scheme 48 の中でプロセススケジューリングの実装に多くの取り組みをしていることを知っています。
3. 効率性。
最近、ついにコンピューターが十分に高速になったように感じられ始めていました。バイトコードについて、つまり余剰サイクルがあるという話を聞くようになってきました。しかし、サーバーベースのソフトウェアではそうではないと思います。サーバーを運用するためのコストを誰かが負担しなければならず、1台のマシンで対応できるユーザー数がその資本コストの分母になるでしょう。
したがって、少なくともボトルネックとなる計算では効率性が重要になると思います。サーバーベースのアプリケーションは I/O を多く行うため、I/O を高速に行うことが特に重要になります。
最終的にはバイトコードが得策ではないかもしれません。Sunとマイクロソフトは現在、バイトコードをめぐる一種の戦いを展開しているようですが、それはバイトコードが自分たちのプロセスに組み込みやすい場所だからであって、バイトコード自体が良いアイデアだからではありません。この戦場全体が迂回されてしまうかもしれません。それは面白いことになるでしょう。
1. クライアント。
これは単なる推測ですが、ほとんどのアプリケーションでは、サーバーベースのモデルが勝者になるのではないかと思います。誰もがあなたのクライアントを持っているという前提でソフトウェアを設計するのは、誰もが正直であるという前提で社会を設計するようなものです。確かに便利かもしれませんが、それは決して起こらないと仮定しなければなりません。
Webアクセスができるデバイスが増えていくと思いますが、それらはシンプルなHTMLとフォームをサポートできるだけだと仮定できるでしょう。携帯電話にブラウザがあるでしょうか?パームパイロットに電話がありますか?BlackBerryの画面が大きくなりますか?ゲームボーイやあなたの腕時計でWebを閲覧できるようになりますか?私にはわかりません。サーバー上にすべてを置いてしまえば、それを知る必要はありません。サーバー上に「頭脳」を置くのは、はるかに堅牢です。
2. オブジェクト指向プログラミング。
これは議論の的になるかもしれませんが、私はオブジェクト指向プログラミングがそんなに大きな問題だとは思いません。ウィンドウシステム、シミュレーション、CADプログラムなど、特定のデータ構造を必要とするアプリケーションには適したモデルだと思います。しかし、それがすべてのプログラミングのモデルであるべき理由は見当たりません。
大企業の人々がオブジェクト指向プログラミングを好む理由の一つは、それが見かけ上多くの作業を生み出すことです。本来リストの整数として表現できるものが、クラスやスキャフォールディング、ハッスルとバタバタとした動きを伴うものとして表現されるのです。
オブジェクト指向プログラミングのもう一つの魅力は、メソッドが一種の高階関数の効果を生み出すことです。しかし、これはLisp プログラマーにとっては古い話です。実際の高階関数があれば、タスクに適したやり方で自由に使えるのに対し、クラスやメソッドにすべてを押し込める必要はありません。
これが言語設計に意味するのは、オブジェクト指向プログラミングを深く組み込みすぎないということです。おそらく、より一般的で基礎的なものを提供し、人々がライブラリとして自分のオブジェクトシステムを設計できるようにするのが答えだと思います。
3. 委員会による設計。
言語を委員会で設計するのは大きな落とし穴で、みんなが知っている理由以外にも問題があります。委員会は凸凹で一貫性のない設計を生み出しがちだということは誰もが知っています。しかし、私が考える更に大きな危険は、委員会はリスクを取らないということです。一人の責任者がいれば、委員会では決して合意できないようなリスクを取ることができます。
では、良い言語を設計するためにリスクを取る必要があるのでしょうか?多くの人は、言語設計は常識に近づいていくべきだと考えるかもしれません。しかし、私はそうではないと賭けます。他のあらゆることでは、リワードはリスクに比例します。なぜ言語設計だけ例外なのでしょうか?