人気者になる
Original2001年5月
(この記事は、新しい言語のようなビジネスプランとして書かれたものです。 そのため、良いプログラミング言語の最も重要な特徴である、非常に強力な抽象化が欠けています。)
私の友人の1人が、著名なオペレーティングシステム専門家に、自分が本当に良いプログラミング言語を設計したいと話したことがあります。その専門家は、プログラミング言語が人気になるかどうかは、その長所に基づいているのではなく、だからこそ、いくら良い言語を設計しても、誰も使わないだろうと言いました。少なくとも、自分が設計した言語がそうなったのだと言っていました。
では、言語が人気になるのはどうしてでしょうか? 人気のある言語は、その人気に値するのでしょうか? 良いプログラミング言語を定義することは意味があるのでしょうか? それはどのようにすればできるのでしょうか?
これらの質問への答えは、ハッカーに注目し、彼らが何を求めているかを学ぶことで見つかると思います。プログラミング言語はハッカーのためにあるものであり、プログラミング言語が良いと言えるのは(たとえば、記号意味論やコンパイラ設計の演習ではなく)、ハッカーが気に入っている場合だけです。
1 人気の仕組み
確かに、ほとんどの人はプログラミング言語の長所に基づいて選択しているわけではありません。ほとんどのプログラマーは、他の誰かに指示されて使う言語を使っています。しかし、そのような外部要因がプログラミング言語の人気に及ぼす影響は、しばしば考えられているほど大きくないと思います。むしろ、ハッカーの考える良いプログラミング言語と、ほとんどの言語設計者の考えるそれとが異なることが、より大きな問題だと思います。
この2つの中で、ハッカーの意見のほうが重要です。プログラミング言語は定理ではなく、人のためのツールであり、人間の長所と短所に合わせて設計されなければなりません。靴が履いた時に痛いのであれば、それは悪い靴なのです。どんなに優雅な彫刻作品であっても。
ほとんどのプログラマーが良い言語と悪い言語を見分けられないかもしれません。しかし、他のツールの場合と同じです。良い言語を設計しようと努力することが無駄だということにはなりません。熟練したハッカーは、良い言語を見分けることができ、それを使うでしょう。熟練したハッカーは少数派かもしれませんが、良いソフトウェアはすべてこの少数派が書いており、彼らの影響力は大きいので、他のプログラマーもその使っている言語を使うようになります。しばしば、単なる影響力ではなく、命令にもなります。つまり、熟練したハッカーが上司や指導教官として、他のプログラマーに使う言語を指示することもあるのです。
プログラミング言語の相対的な人気を決める要因は、専門家ハッカーの意見だけではありません。レガシーソフトウェア(COBOL)やハイプ(Ada、Java)も役割を果たしています。しかし、長期的に見れば、専門家ハッカーの意見が最も強力な力だと思います。初期の重要な利用者がいて、十分な時間があれば、プログラミング言語はおそらくその価値に応じた程度の人気になるでしょう。そして、人気が高まれば、良い言語と悪い言語がさらに分かれていきます。なぜなら、実際のユーザーからのフィードバックが常に改善につながるからです。人気のある言語がその生涯の中でどれだけ変化したかを見てみてください。Perlやフォートランは極端な例ですが、Lispでさえも大きく変わってきました。たとえば、Lisp 1.5にはマクロがありませんでしたが、MITのハッカーがLispを使ってreal programsを書くようになった後に、それらが後に発展したのです。[1]
したがって、良い言語でなくても人気になれるかもしれませんが、人気にならなければ良い言語にはなれません。そして、人気を維持し続けなければ、良い言語でいられません。プログラミング言語の技術は止まることがありません。にもかかわらず、今日のLispは1980年代半ばのMITのものとほとんど変わっていないのは、その当時がLispに十分な大きくて要求の高いユーザーベースがあった最後の時期だったからです。
もちろん、ハッカーがある言語を使うためには、まずそれを知らなければなりません。どのようにして知るのでしょうか? 他のハッカーから聞くのです。しかし、その言語を最初から使っているグループがなければ、他のハッカーにさえ知らせることはできません。この初期のグループがどの程度の大きさである必要があるのか、私には推測しかできません。頭の中では20人くらいだと思います。20人の別々のユーザーがその言語を使うことを決めたのであれば、それは本物だと考えるでしょう。
そこに到達するのは簡単ではないでしょう。0人から20人に到達するのが、20人から1000人に到達するよりも難しいかもしれません。この初期の20人のユーザーを得る最良の方法は、おそらくトロイの木馬を使うことです。つまり、その新しい言語で書かれたアプリケーションを提供し、人々がそれを欲しがるようにすることです。
2 外部要因
まず、プログラミング言語の人気に影響を与える1つの外部要因を認めましょう。プログラミング言語が人気になるためには、人気のあるシステムのスクリプト言語でなければなりません。フォートランとCOBOLは、初期のIBMメインフレームのスクリプト言語でした。Cは、Unixのスクリプト言語でした。そして後にはPerlもそうでした。TclはTkのスクリプト言語です。JavaとJavaScriptは、Webブラウザのスクリプト言語になることを目指しています。
Lispは大衆的な人気がないのは、大衆的に人気のあるシステムのスクリプト言語ではないからです。Lispが今でも人気を保っているのは、1960年代と1970年代、MITのスクリプト言語だった時代の名残りです。当時、多くの偉大なプログラマーがMITと何らかの関係があったのです。そして1970年代初頭、Cが登場する前は、MITのLisp方言であるMacLispが、本格的なハッカーが使いたい唯一のプログラミング言語の1つでした。
今日、LispはEmacs とAutoCADという2つの比較的人気のあるシステムのスクリプト言語ですが、そのため、現在のLisp プログラミングの大部分はEmacs LispやAutoLispで行われていると思います。
プログラミング言語は孤立して存在しているわけではありません。「ハック」は他動詞であり、ハッカーはたいてい何かをハックしています。実際、言語は、それが使われるものに対して相対的に評価されます。したがって、人気のある言語を設計したいのであれば、言語以外のものも提供するか、既存のシステムのスクリプト言語を置き換えるように言語を設計する必要があります。
Common Lispは部分的に人気がないのは、それが孤児であるためです。それは元々Lispマシンというシステムを改造するために作られました。しかし、Lispマシン(そして並列コンピューター)は1980年代の汎用プロセッサの性能向上によって押し潰されてしまいました。Common Lispは、Unixのスクリプト言語として良かったかもしれません。しかし、残念ながら、それは非常に悪いものです。
この状況を説明する1つの方法は、言語が自身の長所によって判断されるのではないと言うことです。別の見方は、プログラミング言語は何かのスクリプト言語でもなければ、プログラミング言語とは呼べないということです。これは驚きとして受け取られるかもしれませんが、不公平ではありません。プログラミング言語にはある程度の実装が必要だと期待するのと同じくらい不公平ではありません。それは、プログラミング言語の一部なのです。
もちろん、プログラミング言語には良い実装が必要で、それは無料でなければなりません。企業は有料のソフトウェアを購入しますが、個人のハッカーは購入しません。そしてそれがハッカーを引き付ける必要があるのです。
言語にはまた、それについての本が必要です。その本は薄く、よく書かれ、良い例で満たされている必要があります。K&Rがここでの理想形です。現時点では、O'Reillyから出版された本を持っていることが、ハッカーにとって重要であるかどうかの試金石になっているといっても過言ではありません。
オンラインのドキュメンテーションも必要です。実際、その本はオンラインのドキュメンテーションから始まることができます。しかし、物理的な本がまだ時代遅れではないと思います。その形式は便利で、出版社による事実上の検閲は(不完全ながら)有用なフィルターとなっています。書店は新しい言語について学ぶ上で最も重要な場所の1つです。
3 簡潔さ
言語に必要な3つのもの - 無料の実装、本、そして何かをハックするためのもの - を提供できるとして、ハッカーに好まれる言語をどのように作ればよいでしょうか?
ハッカーが好むものの1つが簡潔さです。ハッカーは、数学者や近代主義建築家と同じように、怠惰です:余分なものを嫌います。ハッカーがプログラムを書こうとする時、少なくとも無意識のうちに、使う言語を決める際の基準の1つが、タイプしなければならない文字の総数だと言っても過言ではありません。これが正確にハッカーの思考プロセスではなくとも、言語設計者はそうであるかのように振る舞うべきです。
ユーザーを長々とした表現で哄やかすのは間違いです。これはCobolの有名な欠点です。ハッカーにとって、
add x to y giving z
と書かされるのは、自分の知性を侮辱されたと感じるか、神に対する罪悪だと考えるでしょう。
Lispでは、car and cdrの代わりにfirst and restを使うべきだと言われることがあります。それはプログラムをより読みやすくするためだと。最初の数時間はそうかもしれません。しかし、ハッカーはすぐにcarがリストの最初の要素を、cdrがその残りを意味することを学習できます。first and restを使うと、50%多くタイプしなければなりません。また、それらは長さも異なるので、しばしば連続して呼ばれるcarとcdrのように、引数が揃わなくなります。コードがページ上でどのように並ぶかは、私にとってはとても重要です。可変幅フォントでLispコードを読むのはほとんど不可能で、他の言語でも同じだと友人は言っています。
簡潔さは、強く型付けされた言語が劣る点の1つです。他の条件が同じなら、誰もプログラムの冒頭で宣言をする必要はありません。暗黙的にできることは、すべて暗黙的にすべきです。
個々のトークンも短い方が良いです。PerlとCommon Lispは、この点で正反対の極端な例です。Perlのプログラムはほとんど暗号のように密集していますが、Common Lispの組み込み演算子の名前は滑稽なほど長いです。Common Lispの設計者は、ユーザーがこれらの長い名前をテキストエディタで入力してくれることを期待していたのかもしれません。しかし、長い名前のコストは、タイプする手間だけではありません。読む手間と、画面上のスペースを占める手間もあるのです。
4 ハッカビリティ
ハッカーにとって、簡潔さ以上に重要なものがあります。それは、自分の望むことができることです。プログラミング言語の歴史の中で、プログラマーが不適切だと考えられることをするのを防ぐために、驚くほど多くの努力が払われてきました。これは危険な傲慢な計画です。言語設計者がどうやって、プログラマーが必要とするであろうことを予測できるでしょうか? 私は、言語設計者は、自分の予想外のことをする必要があるような天才をターゲットユーザーとして考えるべきだと思います。そうではなく、自分で足を撃つ必要のある人を保護しようとするのは間違いです。そのような人は、間違った問題を解決するために、うまく設計されていないプログラムを書いて、長い時間をかけてしまうでしょう。
優れたプログラマーは、しばしば危険で不快なことをしたいと思います。不快なというのは、言語が提示しようとしている意味論的な外観の裏側にあるものに手を染めることを意味します。例えば、高レベルの抽象化の内部表現を手に入れるなどです。ハッカーはハックすることが好きで、ハックするとは、物事の内部に入り込み、元の設計者を推し量ることです。
自分が推し量られることを許せ。 何かのツールを作ると、人々はあなたの意図しないやり方で使います。これは、プログラミング言語のような高度に構造化されたツールでは特に当てはまります。多くのハッカーは、あなたが想像もしなかったような方法で、意味論的なモデルを書き換えたいと思うでしょう。私は、それを許すべきだと言います。プログラマーにガベージコレクタなどのランタイムシステムを危険にさらすことなく、できるだけ多くの内部情報にアクセスを与えるべきです。
Common Lispでは、しばしば、構造体のフィールドを反復処理したいと思いました。削除されたオブジェクトへの参照を取り除いたり、初期化されていないフィールドを見つけたりするためです。私は、構造体が内部的にはベクトルに過ぎないことを知っています。しかし、任意の構造体に対して呼び出せる汎用的な関数を書くことはできません。フィールドにはそれぞれ名前でしかアクセスできません。なぜなら、それが構造体の意味論的な意味だからです。
ハッカーは、大きなプログラムの中で、意図された模型を裏切るのは1、2回しかないかもしれません。しかし、それができることの違いは大きいのです。そして、単に問題を解決するだけではなく、ある種の喜びもあるのかもしれません。ハッカーは、外科医の内臓をいじくる秘かな喜びや、思春期の子供のニキビを潰す秘かな喜びを共有しているのです。[2] 少なくとも男の子にとって、ある種の恐ろしいものは魅力的なのです。Maximという雑誌は、ピンナップと惨事の写真を混ぜた年間版を出版しています。彼らは読者の心理を知っているのです。
リスプは歴史的に、ハッカーが自分の好きなようにできるようになっていました。コモンリスプの政治的正しさは異常なものです。初期のリスプでは、すべてに手を加えることができました。その精神の多くは、幸いにもマクロに保たれています。ソースコードに任意の変換を加えられるのは素晴らしいことです。
クラシックなマクロは本当のハッカーのツールです - 単純で強力で危険です。それらがどのように機能するかを理解するのは簡単です。マクロの引数に関数を呼び出し、その関数が返すものがマクロ呼び出しの場所に挿入されます。ハイジェニックなマクロは正反対の原則を体現しています。それらは、自分が何をしているのかを理解するのから私を守ろうとします。ハイジェニックなマクロを1文で説明したことは一度も聞いたことがありません。そして、プログラマーが望むことを決めるという危険性の典型的な例です。ハイジェニックなマクロは、変数キャプチャなどから私を守ろうとしますが、変数キャプチャは特定のマクロでは私が望むことなのです。
本当に良い言語は、きれいでも汚れていなければなりません。つまり、よく理解された少数の正交演算子からなる小さな核心部分を持つ洗練された設計であり、一方でハッカーが思いのままに扱えるようになっているということです。Cはそのようなものです。初期のリスプもそうでした。本物のハッカーの言語は常に少し粗野な性格を持っています。
良いプログラミング言語には、「ソフトウェアエンジニアリング」という言葉を使う人々を頭を振らせるような機能が備わっているべきです。対極にあるのが、教育には適していても他には適さないAdaやPascalのような言語です。
5 使い捨てプログラム
ハッカーを魅了するには、その言語が彼らが書きたいプログラムを書くのに適していなければなりません。そしてそれは、意外かもしれませんが、使い捨てプログラムを書くのに適していなければならないということを意味します。
使い捨てプログラムとは、ある限定的な課題のために素早く書くプログラムのことです。システム管理タスクを自動化するプログラム、シミュレーションのテストデータを生成するプログラム、データ形式を変換するプログラムなどです。使い捨てプログラムについての驚くべきことは、第二次世界大戦中にアメリカの多くの大学で建てられた「一時的な」建物のように、実際には捨てられずに進化していくことです。多くの場合、本物のプログラムになり、本物の機能と本物のユーザーを持つようになります。
私の推測では、最高の大規模プログラムは、最初からデカデカと設計されるのではなく、このように始まるのではないかと思います。フーバーダムのように。最初から大規模なものを構築するのは恐ろしいことです。人々があまりにも大きなプロジェクトに取り組むと、圧倒されてしまいます。そのプロジェクトは泥沼に陥るか、結果は無味乾燥で木目細かなものになってしまいます。ショッピングモールではなく本当の市街地、ブラジリアではなくローマのように。
大規模プログラムを得る別の方法は、使い捨てプログラムから始めて、それを徐々に改善していくことです。この方法は恐ろしくはなく、プログラムの設計は進化の恩恵を受けます。私の考えでは、大規模プログラムの多くがこのように開発されていると、調べれば分かるのではないでしょうか。そして、そのように進化したプログラムは、おそらく最初に書かれた言語のままであり、政治的な理由を除いて移植されることはまれです。したがって、皮肉なことに、大規模システムに使われる言語を作るには、使い捨てプログラムを書くのに適していなければならないのです。大規模システムはそこから生まれるからです。
Perlはこのアイデアの顕著な例です。Perlは使い捨てプログラムを書くために設計されただけでなく、ほとんど使い捨てプログラム自体でした。Perlは当初、レポートを生成するためのユーティリティの集まりでしたが、人々がそれに書いた使い捨てプログラムが大きくなるにつれて、プログラミング言語に進化していきました。Perl 5になるまで(もしそうなら)、この言語は本格的なプログラムを書くのに適していませんでしたが、それでも既に大変人気がありました。
使い捨てプログラムに適した言語とはどのようなものでしょうか。まず、すぐに利用できることが重要です。使い捨てプログラムは1時間で書けるものです。したがって、その言語はおそらくあなたが使っているコンピューターにすでにインストールされている必要があります。使う前にインストールしなければならないものではいけません。そこにあるべきなのです。Cはオペレーティングシステムに付属していたので、そこにありました。Perlはシステム管理者のためのツールだったので、あなたのコンピューターにすでにインストールされていました。
利用可能であるということは、インストールされているだけではありません。対話型の言語で、コマンドラインインターフェイスを持っているものの方が、別途コンパイルして実行しなければならないものよりも利用可能です。人気のあるプログラミング言語は対話型で、起動が速いべきです。
使い捨てプログラムに求められるもう1つのことは簡潔さです。ハッカーにとって簡潔さは常に魅力的ですが、1時間で書くプログラムでは特にそうです。
6 ライブラリ
もちろん簡潔さの究極は、プログラムがすでに書かれていて、それを呼び出すだけということです。そしてこれが、私が今後のプログラミング言語の重要な機能になると考えているものにつながります。ライブラリ関数です。Perlが勝つのは、文字列操作の大規模なライブラリを持っているからです。このようなライブラリ関数は、データの変換や抽出を行うことが多い使い捨てプログラムにとって特に重要です。多くのPerlプログラムは、おそらくライブラリ呼び出しをいくつか組み合わせたものから始まっているのではないでしょうか。
今後50年間のプログラミング言語の進歩の多くは、ライブラリ関数に関連するものだと思います。将来のプログラミング言語には、コア言語と同じくらい慎重に設計されたライブラリがあると思います。プログラミング言語の設計は、強い型付けにするか弱い型付けにするか、オブジェクト指向にするか関数型にするかといったことではなく、素晴らしいライブラリをどのように設計するかについてになるでしょう。型システムの設計について考えるのが好きな言語デザイナーは、これに震えあがるかもしれません。それはアプリケーションを書くようなものです!残念ながらそうなのです。言語はプログラマーのためにあり、ライブラリこそがプログラマーに必要なものなのです。
良いライブラリを設計するのは難しいです。多くのコードを書けばいいというわけではありません。ライブラリが大きくなりすぎると、必要な関数を見つけるのに自分で書くよりも時間がかかることさえあります。ライブラリは、コア言語と同じように、少数の正交演算子を使って設計される必要があります。プログラマーが必要なことを行う関数呼び出しを推測できるようになるべきです。
ライブラリは、Common Lispが不足している分野の1つです。文字列操作のためのライブラリは基本的なものしかなく、オペレーティングシステムとの通信のためのライブラリはほとんどありません。歴史的な理由から、Common Lispはオペレーティングシステムの存在を無視しようとしています。そしてオペレーティングシステムとの通信ができないため、Common Lispの組み込み演算子だけでは本格的なプログラムを書くことは難しいでしょう。実装固有のハックを使わざるを得ず、それでもなおかつ望むものが得られないのが現状です。Common Lispに強力な文字列ライブラリとよいオペレーティングシステムサポートがあれば、Lispに対するハッカーの評価は高まるでしょう。
7 構文
Lispの構文、あるいはより正確には構文のなさが、人気のある言語になり得るでしょうか。この質問の答えはわかりません。構文が主な理由でLispが現在人気がないわけではないと思います。Common Lispにはそれ以上の問題があります。prefix構文に慣れた複数のプログラマーがいますが、Perlを標準で使っているのは、強力な文字列ライブラリとオペレーティングシステムとの通信ができるからです。
prefix表記には2つの可能な問題があります。1つは、プログラマーにとって馴染みがないことです。もう1つは、密度が低すぎることです。Lispの世界での一般的な考えは、前者の問題が本当の問題だと考えられています。私はそうは思いません。はい、prefix表記は一般的なプログラマーを動揺させます。しかし、一般的なプログラマーの意見は重要ではありません。言語が人気になるか否かは、エキスパートハッカーがどう考えるかによって決まり、prefix表記に対処できるかもしれません。Perlの構文はかなり理解しにくいですが、それがPerlの人気を阻害してはいません。むしろ、Perlカルトを生み出す一因になっているかもしれません。
より深刻な問題は、prefix表記の拡散性です。これは本当にエキスパートハッカーにとっての問題です。誰も(aref a x y)と書きたくないでしょう。それよりも a[x,y]と書きたいはずです。
この特定の場合、問題を回避する方法があります。データ構造をインデックスに対する関数のように扱えば、(a x y)と書くことができ、Perlの形式よりも短くなります。同様のテクニックを使えば、他の種類の式も短縮できるかもしれません。
多くの括弧を(あるいは省略可能に)なくすには、インデントを意味のあるものにすればよいでしょう。コードを読むときは、インデントが示すものに従っています。インデントを意味のあるものとして扱えば、よくある間違いも解消でき、プログラムも短くなります。
時には中置構文のほうが読みやすいです。特に数式の場合にそうです。プログラミングの生涯を通してLispを使ってきましたが、prefix形式の数式はまだ自然に感じません。しかし、コードを生成する際には、任意の数の引数を取る演算子があると便利です。だからもし中置構文を使うなら、何らかの読み取りマクロとして実装するのがよいでしょう。
Lispに構文を導入することに宗教的に反対する必要はありません。ただし、それがよく理解された方法でs式に変換されるのであれば問題ありません。Lispにはすでに相当の構文が存在します。それ以上の構文を導入するのは悪いことではありません。ただし、誰も使わされるわけではありません。Common Lispでは、いくつかの区切り文字が言語予約されていることから、少なくとも一部の設計者は将来的により多くの構文を導入する計画があったと示唆されています。
Common Lispで最も不Lispらしい構文の1つは、format文字列にあります。formatは独自の言語であり、それはLispではありません。Lispにより多くの構文を導入する計画があれば、formatの指定子をその一部に含めることができるかもしれません。マクロがformat指定子を、他のコードと同様に生成できるようになるのは良いことでしょう。
ある著名なLispハッカーは、自分のCLTLがformatのセクションで開くと言っていました。私も同じです。これは改善の余地があることを示唆しているかもしれません。また、プログラムが多くの入出力を行っていることを意味しているかもしれません。
8 効率性
良い言語は、誰もが知っているように、高速なコードを生成するべきです。しかし実際には、言語設計の中で行うことから高速なコードが得られるわけではありません。Knutが長い間前に指摘したように、速度は特定の重要なボトルネックでのみ問題になります。そして多くのプログラマーが以来観察しているように、これらのボトルネックがどこにあるかを正しく見積もるのは非常に難しいのが現状です。
したがって実際には、強い型付けをするなどといった方法ではなく、非常に良いプロファイラを持つことが高速なコードを得る方法です。すべての呼び出しで引数の型を知る必要はありません。ボトルネックの部分で引数の型を宣言できれば十分です。そしてさらに重要なのは、ボトルネックがどこにあるかを知ることです。
Lispに対する1つの不満は、何が高コストかわかりにくいということです。これは事実かもしれません。抽象度の高い言語であれば、避けられない問題かもしれません。しかし、優れたプロファイラがあれば、この問題は大幅に改善されるはずです。どこが高コストかを素早く学べるはずです。
ここでの問題の一部は社会的なものです。言語設計者は、高速なコンパイラを書くことが得意です。それが自分の技量の測定基準です。プロファイラは付属物程度にしか考えていません。しかし実際には、言語で書かれたプログラムの速度を改善するには、高速なコンパイラよりもよいプロファイラのほうが重要かもしれません。ここでも、言語設計者はユーザーとはかなりかけ離れています。少し違う問題を非常によく解決しているのです。
アクティブなプロファイラを持つのは良いアイデアかもしれません。つまり、プログラマーが問い合わせるのを待つのではなく、パフォーマンスデータをプッシュする方式です。例えば、エディタがソースコード編集時にボトルネックを赤く表示するなどです。別のアプローチとしては、実行中のプログラムの動きを何らかの形で表現することです。これはサーバーベースのアプリケーションで特に大きな効果があるでしょう。実行中のプログラムがたくさんあるからです。アクティブなプロファイラは、プログラムの実行中のメモリ使用状況をグラフィカルに表示したり、発生している出来事を音で知らせたりできるかもしれません。
音は問題を知らせる良いキューになります。以前勤めていた場所では、Webサーバーの状況を示す大きな計器盤がありました。計器の針は小さなサーボモーターで動かされ、わずかな音を立てていました。私の机からは計器盤が見えませんでしたが、サーバーに問題があるとすぐにその音で分かりました。
コンピューター内部で私たちのプログラムを実行している小さな人間がいるとすれば、おそらく連邦政府の職員と同じくらい長く嘆き声を上げているだろう。
多くのLispが現在バイトコードにコンパイルされ、それが解釈実行されるようになっている。これは通常、実装をポータブルにするためだが、言語機能として有用かもしれない。ボトルネックではプログラマーがインラインバイトコードを使えるようにするのが良いアイデアかもしれない。そうすれば最適化もポータブルになる。
ユーザーが関心を持つのは応答時間だ。しかし、別の効率性も重要になってくる。それは1台のプロセッサーで何人の同時ユーザーをサポートできるかという点だ。近い将来に書かれる興味深いアプリケーションの多くがサーバーベースになり、サーバーあたりのユーザー数が重要な問題となる。
長年、エンドユーザーアプリケーションではほとんど効率性が問題にならなかった。開発者は、ユーザーがどんどん強力なプロセッサーを手に入れられると仮定できた。しかし、サーバーベースのアプリケーションでは状況が変わる。ハードウェアとソフトウェアが一緒に提供される。サーバーベースのアプリケーションを提供する企業にとって、1台のサーバーで何人のユーザーをサポートできるかが大きな違いを生む。
9 時間
新しい素晴らしいものを発明した人は、しばしば人々にそのメッセージを繰り返し伝える必要があることに驚かされる。新しいものが登場すると、ほとんどの人は10回ほど聞くまで注意を払わない。大半の新しいものが時間の無駄になり、やがて消えていくからだ。
新しい技術が導入される方法には2つのパターンがある。有機的成長法と大規模発表法だ。有機的成長法は、無名の車庫ベンチャーの典型例だ。数人の開発者が地味に新しい技術を開発し、ユーザーが口コミで広がっていく。一方、大規模発表法は、VCファイナンスを受けた派手なスタートアップの例だ。製品を急いで開発し、大々的に発表して一気に多くのユーザーを獲得しようとする。
10 再設計
「最高の書き物は書き直しである」とE.B.ホワイトは書いた。これは、ソフトウェアにも当てはまる。設計の中で最も重要なのは再設計だ。特にプログラミング言語は、十分に再設計されていない。
良いソフトウェアを書くには、同時に2つの相反するアイデアを頭の中に持っている必要があります。若手ハッカーの能力に対する純真な信仰と、ベテランの懐疑心を持つ必要があります。あなたは、「これほど難しいことがあるだろうか?」と考えながら、「絶対に機能しないだろう」とも考えることができなければなりません。
ここに矛盾はありません。2つの異なるものについて楽観的であり、懐疑的であることが重要なのです。問題を解決する可能性について楽観的であり、現時点での解決策の価値について懐疑的であることが必要です。
優れた仕事をする人は、自分の取り組んでいるものが良くないと考えることが多いです。他の人は彼らの成果に驚嘆しますが、創造者自身は心配に満ちています。このパターンは偶然ではありません。その心配こそが良い仕事を生み出したのです。
希望と心配のバランスを保つことができれば、それらは自転車の2つの足のように、プロジェクトを前に進めていきます。イノベーションのエンジンの最初のフェーズでは、問題を解決できるという自信に駆られて必死に取り組みます。次のフェーズでは、朝の冷めた目で自分の成果を見直し、その欠点をはっきりと認識します。しかし、批判的な精神が希望を上回らない限り、不完全なシステムを見つめ、「これほど難しいことがあるだろうか?」と考え、サイクルを続けることができるのです。
この2つの力のバランスを保つのは難しいです。若手ハッカーは楽観主義が優位を占めています。何かを作り上げ、それが素晴らしいと確信しながら、改善しようとしません。ベテランのハッカーは懐疑主義が優位を占め、野心的なプロジェクトに取り組もうとしません。
再設計のサイクルを続けるためにできることは何でも良いことです。プロセは何度も書き換えられ、満足のいくものになります。しかし、ソフトウェアは通常、十分に再設計されません。プロセには読者がいますが、ソフトウェアにはユーザーがいます。作家が論文を書き換えても、古いバージョンを読んだ人が、新しく導入された非互換性によって考えが乱されることはめったにありません。
ユーザーは両刃の剣です。言語の改善に役立つ一方で、改善を阻害することもあります。ユーザーを慎重に選び、その数を増やすのは遅くすべきです。ユーザーを持つことは最適化と同じで、賢明な方法は遅らせることです。また、一般的に、思っているよりも大幅な変更を加えることができます。変更を導入するのは絆創膏を剥がすようなものです。痛みはすぐに忘れ去られます。
委員会によって設計された言語は良くないというのは誰もが知っています。委員会は悪い設計を生み出します。しかし、委員会の最悪の危険性は、再設計を妨げることだと思います。変更を導入するのは大変な作業なので、誰も面倒がります。委員会が決めたことは、ほとんどのメンバーが気に入らなくても、そのままになりがちです。
2人の委員会でさえ、再設計の障害になります。これは特に、2人の異なる人が書いたソフトウェアの間のインターフェイスで起こります。インターフェイスを変更するには、両者が同時に変更に同意する必要があります。そのため、インターフェイスはほとんど変更されません。これは問題です。なぜなら、インターフェイスは通常、システムの最も ad hoc な部分の1つだからです。
ここでの1つの解決策は、インターフェイスを水平にではなく垂直に設計することです。つまり、モジュールは常に抽象化の垂直方向の層になるようにすることです。そうすれば、インターフェイスは1つのモジュールによって所有されることになります。2つのレベルの下位のものが、上位のものが書かれた言語である場合は下位のレベルがインターフェイスを所有し、下位のものが従属する場合は上位のレベルがインターフェイスを決定できます。
11 Lisp
これらすべてのことから、新しい Lisp に希望があるということがわかります。ハッカーが求めるものを提供する言語であれば、Lisp にも希望があります。Lisp の奇妙さがハッカーを退けているという考えは間違いかもしれません。この安心できる幻想が、Lisp の、少なくともCommon Lispの、本当の問題を見えなくしていたのかもしれません。それは、ハッカーが望むことをするのに適していないということです。ハッカーの言語には強力なライブラリと、ハックできるものが必要です。Common Lispにはそれがありません。ハッカーの言語は簡潔でハックしやすいものですが、Common Lispはそうではありません。
良いニュースは、Lispそのものが問題なのではなく、Common Lispが問題だということです。ハッカーの言語としての真の Lisp を開発できれば、ハッカーはそれを使うでしょう。ハッカーは、仕事をする言語を使うでしょう。私たちがすべきことは、この新しい Lispが他の言語よりも重要な仕事をうまくできるようにすることだけです。
歴史は、ある程度の励ましを与えてくれます。時間とともに、新しい言語が Lisp からますます多くの機能を取り入れてきました。Lispになるまでにあと少しです。最新のホットな言語であるPythonは、マクロのない中置記法の水っぽい Lispです。新しい Lispは、この流れの自然な一歩となるでしょう。
Pythonの改良版と呼ぶのが良いマーケティングのトリックだと思うこともあります。Lispよりもヒップに聞こえます。多くの人にとって、Lispは括弧が多い遅いAI言語です。Fritz Kunzeの公式伝記は、Lの言葉を慎重に避けています。しかし、私の予想では、新しい Lispを Lispと呼ぶことを恐れる必要はありません。Lispは、最高のハッカーの間でまだ尊敬されています。たとえば、6.001を理解した人たちです。そして、そういった人たちこそが、私たちが勝ち取る必要のあるユーザーなのです。
Eric Raymondの「How to Become a Hacker」では、Lispは、ラテン語やギリシャ語のようなものだと説明されています。つまり、実際に使うわけではないが、知的な経験を得るために学ぶべき言語です。
Lispを知らないと、これを読んでいると疑問が湧いてくるでしょう。より良いプログラマになるための言語ということは、より良いプログラミングのための言語ということを意味しているはずです。
この考えが未だに存在する限り、Lispと呼ばれていても、新しい Lispに対してハッカーは受け入れ態勢にあると思います。しかし、この Lispは1970年代の古典的な Lispのようなハッカーの言語でなければなりません。簡潔で、シンプルで、ハックしやすいものでなければなりません。そして、ハッカーが今やりたいことをするための強力なライブラリを持っていなければなりません。
ライブラリの問題については、PerlやPythonのような言語に勝てる余地があると思います。これからの数年間に書かれる必要のある新しいアプリケーションの多くはサーバーベースのアプリケーションになるでしょう。新しいLispが、Perlと同等の優れた文字列ライブラリを持ち、さらにサーバーベースのアプリケーションのための強力なライブラリも持っていれば、非常に人気が出るかもしれません。本物のハッカーは、ライブラリ呼び出しで難しい問題を解決できるような新しいツールを軽視しないでしょう。ハッカーは怠け者だと覚えておいてください。
サーバーベースのアプリケーションのためのコア言語サポートがあれば、さらに大きな勝利になるかもしれません。例えば、複数のユーザーを持つプログラムや、型タグレベルのデータ所有権に対する明示的なサポートなどです。
サーバーベースのアプリケーションは、この新しいLispがどのようなことをハックするために使われるかという問題の答えも教えてくれます。Lispをユニックスのスクリプト言語としてより良くすることも悪くはありません。(悪くするのは難しいでしょう)。しかし、既存の言語よりも勝てる分野があると思います。Tclのモデルに従い、サーバーベースのアプリケーションをサポートするための完全なシステムとともにLispを提供するのが良いかもしれません。Lispはサーバーベースのアプリケーションに自然に適しています。語彙的クロージャーは、UIがウェブページの連続である場合にサブルーチンの効果を得る方法を提供します。S式はHTMLにうまくマッピングされ、マクロはそれを生成するのに適しています。サーバーベースのアプリケーションを書くためのより良いツールが必要であり、新しいLispも必要であり、この2つは非常によく連携するでしょう。
12 ハッカーの夢の言語
要約すると、ハッカーの夢の言語を記述してみましょう。夢の言語は美しく、きれいで、簡潔です。高速に立ち上がるインタラクティブなトップレベルがあります。非常に少ないコードで一般的な問題を解決するプログラムを書くことができます。プログラムに書かれたコードのほとんどすべてがアプリケーション固有のものです。その他のすべてが用意されています。
言語の構文は非常に簡潔です。不要な文字を入力する必要はなく、シフトキーをあまり使う必要もありません。
大きな抽象化を使えば、プログラムの最初のバージョンをとても早く書くことができます。後に最適化したい場合は、注意を向けるべき場所を教えてくれる優れたプロファイラがあります。インナーループを目を見張るほど高速にすることができ、必要に応じてインラインバイトコードを書くこともできます。
学習するのに役立つ良い例がたくさんあり、言語は直感的に使えるので、数分でサンプルから使い方を学べます。マニュアルをあまり見る必要がありません。マニュアルは薄く、警告や留保も少ないです。
この言語には小さなコアがあり、慎重に設計された強力で高度に直交したライブラリがあります。すべてのライブラリが互いによく連携しており、言語の部品がすばらしいカメラのように完璧に組み合わさっています。非推奨の機能や互換性のために残された機能はありません。すべてのライブラリのソースコードは簡単に入手できます。オペレーティングシステムや他の言語で書かれたアプリケーションとの対話が簡単です。
この言語は階層構造になっています。高レベルの抽象化は非常に透明な方法で低レベルの抽象化から構築されており、必要に応じてそれらにアクセスできます。
絶対に隠す必要のないものは何も隠されていません。この言語は作業を節約する方法としてのみ抽象化を提供し、何をすべきかを指示するものではありません。実際、この言語はあなたがその設計に等しい参加者であることを奨励します。構文を含むすべてのものを変更でき、あなたが書くものはできるだけ事前定義のものと同じ地位を持っています。
注
[1] マクロの近代的な概念は1964年にTimothy Hartによって提案されました。これは、Lisp 1.5がリリースされてから2年後のことです。当初欠けていたのは、変数キャプチャと複数の評価を回避する方法でした。Hartの例はこの両方の問題を抱えています。
[2] When the Air Hits Your Brainの中で、脳外科医のFrank Vertosickは、上級レジデントのGaryとの会話を記録しています。Garyは外科医と内科医("ノミ")の違いについて話しています。
Garyと私は大きなピザを注文し、空いているブースを見つけました。上級医は煙草に火をつけました。「あれらのノミどもを見てみろ。一生に一度しか見ないような病気について喋っているんだ。それがノミの問題なんだ。奴らは奇妙なものしか好きじゃない。自分の日常的な仕事は嫌いなんだ。それが我々と奴らの違いなんだ。分かるだろう、我々は大きくて肥えた腰椎ヘルニアが好きなんだが、奴らは高血圧が嫌いなんだ...。
腰椎ヘルニアを「肥えた」と呼ぶのは難しい(文字通りは別として)。しかし、私はそれが何を意味しているのかわかります。私もしばしば美味しいバグを追跡したことがあります。プログラマーでない人には、バグに喜びを感じることがあるとは想像しにくいでしょう。すべてがうまく動けば良いに決まっています。ある意味ではそうですが、特定の種類のバグを追跡することに、否定しがたい暗い満足感があるのも事実です。