Loading...

人気者になる

Original

2001年5月

(この記事は、新しい言語の一種のビジネス プランとして書かれました。そのため、優れたプログラミング言語の最も重要な機能である、非常に強力な抽象化が欠けています (当然のこととして扱っているため)。)

私の友人がかつて、非常に優れたプログラミング言語を設計したいと、著名なオペレーティング システムの専門家に話したことがあります。その専門家は、それは時間の無駄であり、プログラミング言語は、その長所に基づいて人気が出たり不人気になったりするものではないので、その言語がどれだけ優れていても、誰も使わないだろうと言いました。少なくとも、その人が設計した言語はそうなりました。

言語が人気になる理由は何でしょうか? 人気のある言語は人気に値するのでしょうか? 優れたプログラミング言語を定義する価値はあるのでしょうか? どのように定義しますか?

これらの質問の答えは、ハッカーを観察し、彼らが何を求めているかを学ぶことで見つかると思います。プログラミング言語はハッカーのためのものであり、プログラミング言語がプログラミング言語として優れているのは (たとえば、表示的意味論やコンパイラ設計の練習ではなく)、ハッカーがそれを気に入っている場合のみです。

1 人気の仕組み

確かに、ほとんどの人がプログラミング言語をその長所だけで選んでいるわけではないのは事実です。ほとんどのプログラマーは、他の誰かからどの言語を使うべきか指示されます。しかし、そのような外部要因がプログラミング言語の人気に与える影響は、時々考えられているほど大きくないと思います。より大きな問題は、ハッカーが考える良いプログラミング言語が、ほとんどの言語設計者の考える良いプログラミング言語と同じではないということだと思います。

両者のうち、重要なのはハッカーの意見です。プログラミング言語は定理ではありません。プログラミング言語は人間のために設計されたツールであり、靴が人間の足に合わせて設計されなければならないのと同じように、人間の長所と短所に合わせて設計されなければなりません。靴を履いたときに締め付けられるような靴は、彫刻作品としてどれほどエレガントであっても、悪い靴です。

プログラマーの大多数は良い言語と悪い言語の区別がつかないのかもしれない。しかし、それは他のツールでも同じことだ。だからと言って、良い言語を設計しようとするのは時間の無駄だというわけではない。熟練したハッカーは良い言語を見分けることができ、それを使う。熟練したハッカーは確かに少数派だが、その少数派が優れたソフトウェアをすべて書いており、彼らの影響力は他のプログラマーも彼らが使う言語を使う傾向にあるほどだ。実際、それは単なる影響力ではなく命令であることが多い。熟練したハッカーは上司や学部顧問として、他のプログラマーにどの言語を使うべきかを指示する人物であることが多いのだ。

熟練ハッカーの意見は、プログラミング言語の相対的な人気を決定する唯一の力ではありません。レガシーソフトウェア (Cobol) や誇大宣伝 (Ada、Java) も役割を果たしますが、長期的には最も強力な力だと思います。初期のクリティカルマスと十分な時間があれば、プログラミング言語はおそらくその人気に値する程度に人気が出るでしょう。そして、人気は良い言語と悪い言語をさらに区別します。なぜなら、実際のユーザーからのフィードバックは常に改善につながるからです。人気のある言語がその生涯でどれだけ変化してきたかを見てください。Perl と Fortran は極端な例ですが、Lisp でさえ大きく変化しました。たとえば、Lisp 1.5 にはマクロがありませんでした。これは、MIT のハッカーが Lisp を使用して実際のプログラムを記述するのに数年を費やした後に進化しました。[1]

ですから、言語が人気になるために良い言語である必要があるかどうかは別として、良い言語であるためには人気がある言語でなければならないと私は思います。そして、良い言語であり続けるためには、人気を維持する必要があります。プログラミング言語の最先端の技術は留まることはありません。しかし、今日の Lisp は、1980 年代半ばの MIT とほとんど変わりません。なぜなら、Lisp が十分に大きくて要求の厳しいユーザー ベースを持っていた最後の時期だからです。

もちろん、ハッカーは言語を使用する前にその言語について知っておく必要があります。どうやって知るのでしょうか? 他のハッカーから。しかし、他の人がその言語について知るためには、その言語を使用するハッカーの最初のグループが必要です。このグループはどのくらいの大きさでなければならないのでしょうか。何人のユーザーが臨界質量を形成するのでしょうか? すぐに思いつくのは 20 人です。言語に 20 人の個別のユーザーがいる場合、つまり 20 人のユーザーが自分でその言語を使用することを決めたとしたら、私はその言語を本物と見なします。

そこに到達するのは簡単ではないはずです。20 から 1,000 に増やすよりも、0 から 20 に増やす方が難しいとしても、私は驚きません。最初の 20 人のユーザーを獲得する最善の方法は、おそらくトロイの木馬を使用することです。つまり、ユーザーが望むアプリケーションを、たまたま新しい言語で記述したものを提供することです。

2 外部要因

まず、プログラミング言語の人気に影響を与える外部要因を 1 つ認識することから始めましょう。プログラミング言語が人気を得るには、その言語は人気のシステムのスクリプト言語でなければなりません。Fortran と Cobol は初期の IBM メインフレームのスクリプト言語でした。C は Unix のスクリプト言語であり、後に Perl もそうなりました。Tcl は Tk のスクリプト言語です。Java と Javascript は、Web ブラウザーのスクリプト言語として意図されています。

Lisp は、非常に人気のある言語ではありません。なぜなら、非常に人気のあるシステムのスクリプト言語ではないからです。Lisp が今でも人気があるのは、1960 年代から 1970 年代にまで遡ります。当時、Lisp は MIT のスクリプト言語でした。当時の偉大なプログラマーの多くは、MIT と関わりがありました。そして、1970 年代初頭、C が登場する前、MacLisp と呼ばれる MIT の Lisp 方言は、本格的なハッカーが使いたがる数少ないプログラミング言語の 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 つは簡潔さです。数学者や近代主義建築家が怠惰であるのと同じように、ハッカーは怠惰です。彼らは無関係なものを嫌います。プログラムを書こうとしているハッカーが、少なくとも無意識のうちに、入力しなければならない文字の総数に基づいて、使用する言語を決定すると言っても、真実からそれほどかけ離れているわけではありません。これがハッカーの考え方とまったく同じでないなら、言語設計者は、ハッカーがそうであるかのように行動するのが賢明です。

英語に似せて長ったらしい表現でユーザーを甘やかそうとするのは間違いです。Cobolはこの欠陥で有名です。ハッカーは次のように書くように頼まれたらどうするか考えるでしょう。

x に y を加えて z を得る

の代わりに

z=x+y

それは彼の知性に対する侮辱であり、神に対する罪である。

Lisp では car と cdr ではなく first と rest を使うべきだと言われることがあります。その方がプログラムが読みやすくなるからです。最初の数時間はそうかもしれません。しかしハッカーは car がリストの最初の要素を意味し、cdr が残りを意味することをすぐに学習します。first と rest を使用すると、入力が 50% 増えます。また、長さも異なるため、car と cdr が連続した行で呼び出される場合のように、引数が揃いません。コードがページ上でどのように並ぶかは、非常に重要であることがわかりました。Lisp のコードが可変幅フォントで設定されていると、ほとんど読めません。友人によると、これは他の言語でも同じだそうです。

簡潔さは、強く型付けされた言語が負ける点の 1 つです。他の条件が同じであれば、誰も大量の宣言でプログラムを開始したいとは思いません。暗黙的にできるものはすべて、暗黙的に行うべきです。

個々のトークンも短くする必要があります。Perl と Common Lisp は、この問題に関して正反対の立場を取っています。Perl プログラムは暗号のように難解ですが、Common Lisp の組み込み演算子の名前は滑稽なほど長いです。Common Lisp の設計者は、おそらくユーザーがこれらの長い名前を入力するテキスト エディターを持っていることを想定していました。しかし、長い名前のコストは、入力コストだけではありません。読むコストや、画面上で占めるスペースのコストもあります。

4 ハッキング可能性

ハッカーにとって簡潔さよりも重要なことが 1 つあります。それは、やりたいことができることです。プログラミング言語の歴史において、プログラマーが不適切と見なされる行為をしないようにするために、驚くほど多くの努力が払われてきました。これは危険なほど思い上がりの計画です。言語設計者は、プログラマーが何をしなければならないかをどうやって知ることができるでしょうか。言語設計者は、ターゲット ユーザーを、自分自身から保護される必要のある不器用な人ではなく、予想もしなかったことをしなければならない天才と考えたほうがよいと思います。不器用な人は、いずれにせよ自ら足を撃ちます。別のパッケージの変数を参照することから彼を救えるかもしれませんが、間違った問題を解決するために設計の悪いプログラムを書いて、それをするのに永遠にかかることから彼を救うことはできません。

優秀なプログラマーは、危険で不愉快なことをしたがることがよくあります。不愉快なこととは、言語が提示しようとしている意味的な表面の背後にあることを意味します。たとえば、高レベルの抽象化の内部表現を取得するなどです。ハッカーはハッキングを好みますが、ハッキングとは内部に入り込み、元の設計者を推測することを意味します。

*自分で考え直しましょう。*どんなツールを作るときも、人々はそれをあなたが意図しない方法で使います。これはプログラミング言語のような高度に表現されたツールの場合に特に当てはまります。多くのハッカーはあなたが想像もしなかった方法であなたのセマンティック モデルをいじりたがるでしょう。私は、彼らにそうさせてください、ガベージ コレクターのようなランタイム システムを危険にさらすことなく、できるだけ多くの内部情報にプログラマーがアクセスできるようにします。

Common Lisp では、構造体のフィールドを反復処理したいことがよくありました。たとえば、削除されたオブジェクトへの参照をくまなく調べたり、初期化されていないフィールドを見つけたりしたい場合です。構造体は実際には単なるベクターであることはわかっています。しかし、どの構造体でも呼び出せる汎用関数を書くことはできません。構造体は名前でしかフィールドにアクセスできません。それが本来の意味だからです。

ハッカーは、大規模なプログラムで、意図されたモデルを一度か二度覆したいだけかもしれません。しかし、それができると、大きな違いが生まれます。そして、それは単に問題を解決する以上のことかもしれません。ここには、ある種の喜びもあります。ハッカーは、外科医が汚い内臓をいじる秘密の喜び、ティーンエイジャーがニキビを潰す秘密の喜びを共有しています。[2] 少なくとも男の子にとっては、ある種の恐怖は魅力的です。マキシム誌は、ピンナップと陰惨な事故を混ぜた写真集を毎年発行しています。彼らは読者を知っています。

歴史的に見て、Lisp はハッカーのやりたいようにやらせるのが得意でした。Common Lisp の政治的正しさは例外です。初期の Lisp では、何でも自由に操作できました。幸いなことに、その精神の多くはマクロに保存されています。ソース コードを任意に変換できるのは、なんとすばらしいことでしょう。

古典的なマクロは、まさにハッカーのツールです。単純で強力、そして危険です。マクロの動作は簡単に理解できます。マクロの引数で関数を呼び出すと、マクロ呼び出しの代わりにその戻り値が挿入されます。衛生的なマクロは、その逆の原理を体現しています。マクロは、マクロの動作を理解できないように保護します。私は、衛生的なマクロが一文で説明されているのを聞いたことがありません。また、これは、プログラマーが望むことを許されるものを決めることの危険性を示す典型的な例です。衛生的なマクロは、変数キャプチャなどからユーザーを保護することを目的としていますが、一部のマクロでは変数キャプチャこそがまさに私が望んでいるものです。

本当に良い言語は、クリーンでありながらダーティでもあるべきです。つまり、よく理解され、高度に直交する演算子の小さなコアを備え、クリーンに設計されているが、ハッカーが自由に使えるという意味でダーティであるべきです。C はこれに似ています。初期の Lisp もそうでした。本物のハッカーの言語には、常に少し乱暴な性格があります。

優れたプログラミング言語には、「ソフトウェア エンジニアリング」というフレーズを使う人々が首を横に振って不満を抱くような機能が必要です。その対極にあるのが Ada や Pascal などの言語で、これらは教育には適していますが、それ以外にはあまり役に立ちません。

5つの使い捨てプログラム

ハッカーにとって魅力的な言語であるためには、言語はハッカーが書きたい種類のプログラムを書くのに適していなければなりません。そして、おそらく意外かもしれませんが、それは使い捨てのプログラムを書くのに適していなければならないことを意味します。

使い捨てプログラムとは、システム管理タスクを自動化するプログラム、シミュレーション用のテスト データを生成するプログラム、またはデータをある形式から別の形式に変換するプログラムなど、限られたタスクのために素早く作成するプログラムです。使い捨てプログラムに関して驚くべきことは、第二次世界大戦中に多くのアメリカの大学に建てられた「仮設」の建物のように、使い捨てプログラムが捨てられないことが多いことです。その多くは、実際の機能と実際のユーザーを持つ実際のプログラムに進化します。

フーバーダムのように最初から大きく設計されるのではなく、最高の大規模プログラムはこのようにして誕生するのではないかという予感がします。ゼロから何か大きなものを作るのは恐ろしいことです。大きすぎるプロジェクトに取り組んだ人は圧倒されてしまいます。プロジェクトは行き詰まるか、または結果は不毛で無味乾燥なものになります。本物のダウンタウンではなくショッピングモール、ローマではなくブラジリア、C ではなく Ada です。

大きなプログラムを作成する別の方法は、使い捨てのプログラムから始めて、それを改良し続けることです。このアプローチはそれほど困難ではありませんし、プログラムの設計は進化の恩恵を受けます。よく考えてみると、これがほとんどの大きなプログラムが開発された方法であることがわかります。そして、このように進化したプログラムは、おそらく最初に書かれた言語で書かれ続けています。なぜなら、政治的な理由を除いて、プログラムが移植されることはまれだからです。したがって、逆説的ですが、大きなシステムに使用される言語を作りたい場合、使い捨てのプログラムを書くのに適した言語にする必要があります。なぜなら、大きなシステムは使い捨てのプログラムから生まれるからです。

Perl はこの考え方の顕著な例です。Perl は使い捨てプログラムを書くために設計されただけでなく、それ自体が使い捨てプログラムでした。Perl はレポートを生成するユーティリティのコレクションとして誕生し、人々が書いた使い捨てプログラムが大きくなるにつれてプログラミング言語へと進化しました。Perl 5 (当時であれば) になって初めて、この言語は本格的なプログラムを書くのに適するようになりましたが、それでもすでに非常に人気がありました。

使い捨てプログラムに適した言語とはどのようなものでしょうか。まず、その言語はすぐに利用できるものでなければなりません。使い捨てプログラムとは、1 時間で作成できると予想されるものです。したがって、その言語は、使用しているコンピュータにすでにインストールされている必要があります。使用する前にインストールしなければならないものであってはなりません。そこに存在していなければなりません。C がそこにあったのは、オペレーティング システムに付属していたからです。Perl がそこにあったのは、もともとシステム管理者用のツールであり、すでにインストールされていたからです。

ただし、利用可能であることは、インストールされていること以上の意味を持ちます。コマンドライン インターフェイスを備えた対話型言語は、個別にコンパイルして実行する必要がある言語よりも利用可能です。人気のあるプログラミング言語は、対話型で、起動が速い必要があります。

使い捨てプログラムに必要なもう 1 つの要素は、簡潔さです。ハッカーにとって簡潔さは常に魅力的ですが、1 時間で完成すると期待されるプログラムでは特に魅力的です。

6 ライブラリ

もちろん、簡潔さの極みは、プログラムが既に作成されていて、それを呼び出すだけであることです。そして、これは、プログラミング言語のますます重要な機能になると思われるライブラリ関数につながります。Perl が勝っているのは、文字列を操作するための大規模なライブラリがあるためです。このクラスのライブラリ関数は、使い捨てプログラムにとって特に重要です。使い捨てプログラムは、もともとデータの変換や抽出のために作成されることが多いです。多くの Perl プログラムは、おそらく、いくつかのライブラリ呼び出しがくっついたものから始まります。

今後 50 年間にプログラミング言語で起こる進歩の多くは、ライブラリ関数に関係すると思います。将来のプログラミング言語には、コア言語と同じくらい注意深く設計されたライブラリが含まれると思います。プログラミング言語の設計は、言語を強く型付けするか弱く型付けするか、オブジェクト指向にするか関数型にするか、あるいはその他のものにするかではなく、優れたライブラリをどのように設計するかについてです。型システムの設計方法を考えるのが好きな言語設計者は、これにぞっとするかもしれません。まるでアプリケーションの作成のようです。残念です。言語はプログラマーのためのものであり、ライブラリはプログラマーが必要とするものなのです。

優れたライブラリを設計するのは難しいことです。単に大量のコードを書けばよいということではありません。ライブラリが大きくなりすぎると、必要な関数を見つけるのに自分でコードを書くよりも時間がかかることがあります。ライブラリは、コア言語と同様に、少数の直交演算子を使用して設計する必要があります。プログラマーは、どのライブラリ呼び出しが必要なことを実行するかを推測できる必要があります。

ライブラリは Common Lisp が不十分な点の 1 つです。文字列を操作するための基本的なライブラリしかなく、オペレーティング システムと通信するためのライブラリはほとんどありません。歴史的な理由から、Common Lisp は OS が存在しないかのように振る舞います。また、OS と通信できないため、Common Lisp の組み込み演算子のみを使用して本格的なプログラムを作成することは不可能です。実装固有のハックもいくつか使用する必要がありますが、実際には、これらでは必要なものがすべて得られるとは限りません。Common Lisp に強力な文字列ライブラリと優れた OS サポートがあれば、ハッカーは Lisp をもっと高く評価するでしょう。

7 構文

Lisp の構文、より正確には構文がない言語が人気になる可能性はあるでしょうか? この質問の答えはわかりません。Lisp が現在人気がない主な理由は構文ではないと思います。Common Lisp には馴染みのない構文よりも悪い問題があります。プレフィックス構文に慣れていながら、強力な文字列ライブラリがあり OS と通信できるため、デフォルトで Perl を使用するプログラマーを何人か知っています。

プレフィックス表記法には 2 つの問題が考えられます。プログラマーに馴染みがないということと、十分に理解されていないということです。Lisp の世界では、最初の問題が本当の問題だというのが通説です。私はそうは思いません。確かに、プレフィックス表記法は普通のプログラマーをパニックに陥れます。しかし、普通のプログラマーの意見は重要ではないと思います。言語の人気や不人気は、熟練したハッカーの意見によって決まります。熟練したハッカーならプレフィックス表記法に対処できると思います。Perl の構文はかなり理解しにくいかもしれませんが、それが Perl の人気の妨げにはなっていません。むしろ、Perl カルトを育むのに役立ったかもしれません。

さらに深刻な問題は、プレフィックス表記の曖昧さです。熟練したハッカーにとって、これは本当に問題です。a[x,y] と書けるのに (aref axy) と書きたい人はいません。

この特定のケースでは、問題を巧みに解決する方法があります。データ構造をインデックスの関数のように扱うと、代わりに (axy) と記述できます。これは Perl 形式よりもさらに短くなります。同様のトリックで、他の種類の式も短くすることができます。

インデントを重要視することで、多くの括弧をなくす(または省略可能にする)ことができます。プログラマーはとにかくそのようにコードを読みます。インデントと区切り記号が別の意味を持つ場合、インデントを基準にします。インデントを重要視することで、このよくあるバグの原因を排除できるだけでなく、プログラムも短くなります。

場合によっては、中置構文の方が読みやすいことがあります。これは特に数式に当てはまります。私はプログラミング人生を通じてずっと Lisp を使ってきましたが、それでも前置数式が自然だとは思いません。しかし、特にコードを生成するときには、任意の数の引数を取る演算子があると便利です。したがって、中置構文を使用する場合は、何らかの読み取りマクロとして実装する必要があります。

Lisp に構文を導入することに、それが基礎となる S 式によく理解できる方法で変換される限り、宗教的に反対する必要はないと思います。Lisp にはすでに多くの構文があります。誰もそれを使用することを強制されない限り、さらに構文を導入することは必ずしも悪いことではありません。Common Lisp では、一部の区切り文字が言語用に予約されており、少なくとも一部の設計者は将来的に構文を増やすつもりだったことがうかがえます。

Common Lisp の構文の中で最も Lisp らしくない部分の 1 つは、書式文字列にあります。書式はそれ自体が言語であり、その言語は Lisp ではありません。Lisp にさらに多くの構文を導入する計画があれば、書式指定子をそれに含めることができるかもしれません。マクロが他の種類のコードを生成するのと同じように書式指定子を生成できれば良いでしょう。

著名な Lisp ハッカーが、彼の CLTL のコピーはセクション形式にオープンであると私に言いました。私のものも同様です。これはおそらく改善の余地があることを示しています。また、プログラムが大量の I/O を実行することも意味している可能性があります。

8 効率

誰もが知っているように、優れた言語は高速なコードを生成するはずです。しかし、実際には、高速なコードは主に言語の設計で行われる作業から生まれるとは思いません。Knuth がずっと前に指摘したように、速度は特定の重大なボトルネックでのみ重要です。そして、それ以来多くのプログラマーが気づいたように、これらのボトルネックがどこにあるかについては、非常によく誤解されています。

したがって、実際には、高速なコードを得るには、言語を強く型付けするよりも、非常に優れたプロファイラーを使用するのがよいでしょう。プログラムのすべての呼び出しのすべての引数の型を知る必要はありません。ボトルネックの引数の型を宣言できる必要があります。さらに、ボトルネックがどこにあるかを見つけられる必要があります。

Lisp に関して人々が抱く不満の 1 つは、何がコストが高いのかがわかりにくいということです。これは本当かもしれません。また、非常に抽象的な言語を使いたい場合、これは避けられないことかもしれません。いずれにせよ、適切なプロファイリングが問題の解決に大いに役立つと思います。何がコストが高いのかがすぐにわかるでしょう。

ここでの問題の一部は社会的なものです。言語設計者は高速なコンパイラを書くのが好きです。それが彼らのスキルを測る基準です。彼らはプロファイラをせいぜいアドオンとしか考えていません。しかし実際には、高速なコードを生成するコンパイラよりも、優れたプロファイラの方が、その言語で書かれた実際のプログラムの速度を向上させることができます。ここでも、言語設計者はユーザーと少し疎遠になっています。彼らは、少し間違った問題を解決することに非常に優れています。

アクティブ プロファイラーを用意して、パフォーマンス データをプログラマーにプッシュし、プログラマーが要求してくるのを待つのを待つのは良い考えかもしれません。たとえば、プログラマーがソース コードを編集するときに、エディターでボトルネックを赤で表示できます。別のアプローチとしては、実行中のプログラムで何が起こっているかを何らかの方法で表すというものがあります。これは、多数の実行中のプログラムを確認する必要があるサーバー ベースのアプリケーションでは特に大きなメリットになります。アクティブ プロファイラーは、プログラムの実行中にメモリ内で何が起こっているかをグラフィカルに表示したり、何が起こっているかを示す音を鳴らしたりすることもできます。

音は問題を知るよい手がかりです。私が働いていたある場所には、Web サーバーで何が起こっているかを示す大きなダイヤル ボードがありました。針は小さなサーボモーターによって動かされ、回転するとかすかな音がします。デスクからはボードが見えませんでしたが、サーバーに問題があると音ですぐにわかることが分かりました。

非効率的なアルゴリズムを自動的に検出するプロファイラーを書くことも可能かもしれません。特定のメモリ アクセス パターンが、悪いアルゴリズムの確かな兆候であることが判明しても、私は驚きません。コンピューター内でプログラムを実行する小さな男が走り回っていたら、連邦政府職員としての自分の仕事について、おそらく長くて悲しげな話をするでしょう。私は、プロセッサを無駄な努力に送り込んでいるような気がしますが、プロセッサが何をしているのかを調べる良い方法をこれまで一度も持っていませんでした。

現在、多くの Lisp はバイト コードにコンパイルされ、インタープリタによって実行されます。これは通常、実装の移植を容易にするために行われますが、便利な言語機能になる可能性もあります。バイト コードを言語の公式な一部にして、プログラマがボトルネックでインライン バイト コードを使用できるようにすることは良い考えかもしれません。そうすれば、このような最適化も移植可能になります。

エンド ユーザーが認識する速度の性質は変化している可能性があります。サーバー ベースのアプリケーションの増加に伴い、ますます多くのプログラムが I/O 依存になる可能性が出てきます。I/O を高速化することは価値があります。この言語は、シンプルで高速なフォーマット済み出力関数などの直接的な手段だけでなく、キャッシュや永続オブジェクトなどの深い構造変更にも役立ちます。

ユーザーは応答時間に興味があります。しかし、別の種類の効率性、つまりプロセッサごとにサポートできる同時ユーザー数もますます重要になります。近い将来に作成される興味深いアプリケーションの多くはサーバーベースになるため、サーバーあたりのユーザー数は、そのようなアプリケーションをホストするすべての人にとって重要な問題です。サーバーベースのアプリケーションを提供するビジネスの資本コストでは、これが除数になります。

長年、ほとんどのエンドユーザー アプリケーションでは効率性はあまり重要ではありませんでした。開発者は、各ユーザーのデスクにはますます強力なプロセッサが搭載されるだろうと想定してきました。そして、パーキンソンの法則により、ソフトウェアは利用可能なリソースを使用するように拡張されました。サーバー ベースのアプリケーションでは状況が変わります。その世界では、ハードウェアとソフトウェアが一緒に提供されます。サーバー ベースのアプリケーションを提供する企業にとって、サーバー 1 台あたり何人のユーザーをサポートできるかが、最終的な収益に非常に大きな影響を及ぼします。

アプリケーションによっては、プロセッサが制限要因となり、実行速度を最適化することが最も重要になります。しかし、多くの場合、メモリが制限となります。同時ユーザー数は、各ユーザーのデータに必要なメモリの量によって決まります。言語もここで役立ちます。スレッドのサポートが優れていると、すべてのユーザーが単一のヒープを共有できます。永続オブジェクトや言語レベルの遅延読み込みのサポートも役立つ場合があります。

9 時間

人気のある言語に必要な最後の要素は時間です。多くのプログラミング言語のように、消えてしまうかもしれない言語でプログラムを書きたい人はいません。そのため、ほとんどのハッカーは、言語が数年登場するまで待ってから、その言語の使用を検討する傾向があります。

素晴らしい新発明を発明した人は、このことに気付いて驚くことが多いのですが、人々にメッセージを伝えるには時間が必要です。私の友人は、誰かに頼まれたらすぐに何かをすることはめったにありません。人は、後で欲しくないものを頼むことがあると知っています。時間を無駄にしないために、何かを頼まれるのは 3 回目か 4 回目まで待ちます。その頃には、頼んだ人はかなりイライラしているかもしれませんが、少なくとも頼んでいるものは何でも本当に欲しいと思っているはずです。

ほとんどの人は、耳にする新しいものに対して、同じようなフィルタリングを行うことを学んでいます。何かについて 10 回聞くまでは、注意を払うことさえしません。それはまったく当然のことです。話題の新しいもののほとんどは、結局は時間の無駄になり、やがて消え去ってしまうからです。VRML の学習を遅らせることで、私は VRML をまったく学習せずに済みました。

ですから、何か新しいものを発明する人は、人々に理解されるまで何年もそのメッセージを繰り返し伝え続ける覚悟が必要です。私たちが書いたのは、私が知る限りでは初の Web サーバー ベースのアプリケーションでしたが、ダウンロードする必要がないことを人々に理解してもらうのに何年もかかりました。彼らが愚かだったわけではありません。ただ私たちの話に耳を傾けなかったのです。

幸いなことに、単純な繰り返しで問題は解決します。あなたがしなければならないのは、自分のストーリーを語り続けることだけです。そうすれば、やがて人々は耳を傾け始めます。人々が注意を払うのは、あなたがそこにいることに気付いたときではなく、あなたがまだそこにいることに気付いたときです。

勢いがつくまでに時間がかかるのも、当然のことです。ほとんどのテクノロジーは、最初にリリースされた後でもかなり進化します。プログラミング言語は特にそうです。新しいテクノロジーにとって、数年は少数のアーリーアダプターによってのみ使用されることほど良いことはありません。アーリーアダプターは洗練されていて要求が厳しく、テクノロジーに残っている欠陥をすぐに洗い出します。ユーザーが少数であれば、その全員と密接な関係を築くことができます。また、アーリーアダプターは、たとえ何らかの不具合が発生しても、システムの改善を許容してくれます。

新しい技術が導入される方法は 2 つあります。有機的成長法とビッグバン法です。有機的成長法は、典型的な、資金不足のガレージ スタートアップで、行き当たりばったりの典型的な例です。無名で働く 2 人の男性が、新しい技術を開発します。彼らはマーケティングなしでそれをリリースし、当初は少数の (熱狂的な) ユーザーしかいません。彼らは技術を改良し続け、その間に口コミでユーザー ベースが拡大します。彼らは知らないうちに、大きな企業になっています。

もう 1 つのアプローチであるビッグバン方式は、ベンチャー キャピタルの支援を受け、大々的に宣伝するスタートアップ企業に代表されます。彼らは急いで製品を開発し、大々的に宣伝して発売し、すぐに (期待通り) 大規模なユーザー ベースを獲得します。

一般的に、ガレージ派はビッグバン派を羨ましがります。ビッグバン派は、洗練されていて自信に満ちており、ベンチャーキャピタルから尊敬されています。彼らはあらゆる面で最高のものを買う余裕があり、ローンチをめぐる PR キャンペーンは、彼らを有名人にするという副作用があります。一方、オーガニック グロース派は、ガレージにこもり、貧しく、愛されていないと感じています。しかし、彼らが自分を哀れに思うのは間違いだと思います。オーガニック グロースは、ビッグバン方式よりも優れたテクノロジーと裕福な創業者を生み出すようです。今日の主流のテクノロジーを見ると、そのほとんどがオーガニックに成長したことがわかります。

このパターンは企業だけに当てはまるわけではありません。スポンサー付きの研究でも見られます。Multics と Common Lisp はビッグバン プロジェクトであり、Unix と MacLisp は有機的な成長プロジェクトでした。

10 再設計

「最高の文章とは書き直すことだ」と EB White は書いています。優れた作家なら誰でもこのことは知っていますが、これはソフトウェアにも当てはまります。設計の最も重要な部分は再設計です。特にプログラミング言語は十分に再設計されていません。

良いソフトウェアを書くには、頭の中に相反する 2 つの考えを同時に持たなければなりません。若いハッカーが自分の能力に抱く素朴な信頼と、ベテランが抱く懐疑心を同時に持つ必要があります。脳の片方で「そんなに難しいことなのだろうか?」と考えながら、もう片方の脳で「絶対にうまくいかないだろう」と考えることができなければなりません。

重要なのは、ここには実際の矛盾はないということに気づくことです。2 つの異なる事柄について楽観的かつ懐疑的になりたいのです。問題を解決できる可能性については楽観的であるべきですが、これまでに得た解決策の価値については懐疑的である必要があります。

良い仕事をする人は、自分が取り組んでいることは何でも良くないと考えることが多い。他の人は彼らの仕事を見て驚きますが、創造者は心配でいっぱいです。このパターンは偶然ではありません。心配するからこそ、仕事は良くなるのです。

希望と不安のバランスを保つことができれば、2 本の足が自転車を前に進めるのと同じように、プロジェクトを前に進めることができます。2 サイクル イノベーション エンジンの最初のフェーズでは、問題を解決できるという自信に刺激されて、ある問題に猛烈に取り組みます。2 番目のフェーズでは、朝の冷静な光の中で自分が行ったことを振り返り、そのすべての欠陥を非常に明確に認識します。しかし、批判精神が希望を上回らない限り、明らかに不完全なシステムを見て、残りの道のりを進むのにどれほど難しいことだろうかと考え、サイクルを継続することができます。

2 つの力のバランスを保つのは困難です。若いハッカーの場合、楽観主義が優勢です。何かを作り、それが素晴らしいと確信しますが、決して改良しません。年配のハッカーの場合、懐疑主義が優勢で、野心的なプロジェクトに取り組む勇気さえありません。

再設計サイクルを継続するためにできることは何でも良いことです。散文は、満足するまで何度でも書き直すことができます。しかし、ソフトウェアは、原則として、十分に再設計されません。散文には読者がいますが、ソフトウェアには*ユーザーがいます。*作家がエッセイを書き直した場合、古いバージョンを読んだ人が、新たに導入された非互換性によって自分の考えが崩れたと文句を言う可能性は低いでしょう。

ユーザーは諸刃の剣です。言語の改善を助けてくれる一方で、改善を阻むこともあります。そのため、ユーザーは慎重に選び、その数を増やすのはゆっくりにしてください。ユーザーを持つことは最適化に似ています。賢明な方法は、それを遅らせることです。また、原則として、いつでも、あなたが思っている以上に多くの変更をしても大丈夫です。変更を導入することは、包帯を剥がすようなものです。痛みは、感じた瞬間に記憶に残ります。

言語を委員会で設計するのは得策ではないことは誰もが知っています。委員会は悪い設計を生み出します。しかし、委員会の最大の危険は再設計を妨害することだと思います。変更を導入するのは非常に手間がかかるため、誰も面倒に思いません。委員会が決定したことは、たとえほとんどのメンバーが気に入らなくても、そのままになる傾向があります。

たとえ 2 人の委員会であっても、再設計の妨げになります。これは、2 人の異なる人が作成したソフトウェア間のインターフェイスで特に発生します。インターフェイスを変更するには、両者が同時に変更に同意する必要があります。そのため、インターフェイスはまったく変更されない傾向があり、これは問題です。なぜなら、インターフェイスはシステムの中で最もアドホックな部分の 1 つである傾向があるからです。

ここでの 1 つの解決策は、インターフェイスが垂直ではなく水平になるようにシステムを設計することです。つまり、モジュールが常に垂直に積み重ねられた抽象化の層になるようにします。そうすると、インターフェイスはどちらか一方によって所有される傾向があります。2 つのレベルのうち下位のレベルは、上位のレベルが記述されている言語であるか、下位のレベルがインターフェイスを所有するかのいずれかになります。下位のレベルは、上位のレベルによってインターフェイスが指示されるスレーブになります。

11 リスプ

これらすべてが意味するのは、新しい Lisp に希望があるということです。Lisp を含め、ハッカーが望むものを提供する言語には希望があります。Lisp の奇妙さがハッカーを遠ざけると考えるのは間違いだったと思います。この安心できる幻想が、Lisp、少なくとも Common Lisp の本当の問題、つまりハッカーがやりたいことを実現するには 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 を入手して理解したような、最高のハッカーたちの間では、依然として潜在的な尊敬を集めている。そして、あなたが勝ち取るべきユーザーとは、まさにこの人たちだ。

「ハッカーになる方法」の中で、エリック・レイモンドは Lisp をラテン語やギリシャ語のようなもの、つまり、実際には使わないとしても知的な訓練として学ぶべき言語として説明しています。

Lisp は、最終的に理解したときに得られる深い啓蒙体験のために学ぶ価値があります。たとえ実際に Lisp 自体をあまり使用しなくても、その体験によって、あなたは生涯を通じてより優れたプログラマーになれるでしょう。

もし私が Lisp を知らなかったら、これを読んで疑問が湧いてくるでしょう。私をより優れたプログラマーにしてくれる言語は、もしそれが何を意味するとしても、プログラミングに適した言語を意味します。そして、それが実際に Eric が言っていることの含意です。

そのアイデアがまだ広まっている限り、たとえそれが Lisp と呼ばれていたとしても、ハッカーたちは新しい Lisp に十分受け入れるだろうと私は思います。しかし、この Lisp は、1970 年代の古典的な Lisp のように、ハッカーの言語でなければなりません。簡潔で、シンプルで、ハッキング可能でなければなりません。そして、ハッカーが今やりたいことを実現するための強力なライブラリを備えていなければなりません。

ライブラリに関しては、Perl や Python のような言語をその得意分野で打ち負かす余地があると思います。今後数年間に作成する必要のある新しいアプリケーションの多くは、サーバーベースのアプリケーションになります。新しい Lisp に Perl と同じくらい優れた文字列ライブラリがない理由はありません。また、この新しい Lisp にサーバーベースのアプリケーション用の強力なライブラリがあれば、非常に人気が出る可能性があります。本物のハッカーは、いくつかのライブラリ呼び出しで難しい問題を解決できる新しいツールを鼻であしらったりはしません。ハッカーは怠け者だということを忘れないようにしましょう。

サーバーベースのアプリケーションにコア言語のサポートがあれば、さらに大きなメリットが得られる可能性があります。たとえば、複数のユーザーがいるプログラムの明示的なサポートや、型タグのレベルでのデータ所有権などです。

サーバーベースのアプリケーションは、この新しい Lisp が何をハックするために使用されるかという疑問に対する答えも与えてくれます。Unix のスクリプト言語として Lisp を改良しても害にはなりません (悪化させるのは難しいでしょう)。しかし、既存の言語の方が簡単に勝てる分野もあると思います。Tcl のモデルに従い、サーバーベースのアプリケーションをサポートするための完全なシステムと一緒に Lisp を提供する方が良いのではないかと思います。Lisp はサーバーベースのアプリケーションに自然に適合します。UI が一連の Web ページである場合、字句クロージャによってサブルーチンの効果を得ることができます。S 式は HTML にうまくマッピングされ、マクロはそれを生成するのに適しています。サーバーベースのアプリケーションを作成するためのより優れたツールが必要であり、新しい Lisp が必要です。そして、この 2 つは非常にうまく連携します。

12 夢の言語

まとめとして、ハッカーの夢の言語について説明してみましょう。夢の言語は美しく、簡潔で、起動が速い対話型のトップレベルを備えています。ごくわずかなコードで、一般的な問題を解決するプログラムを作成できます。作成するプログラムのほぼすべてのコードは、アプリケーションに固有のコードです。他のすべては自動的に行われます。

この言語の構文は簡潔で、無駄な文字を入力したり、Shift キーを頻繁に使用したりする必要がありません。

大きな抽象化を使用すると、プログラムの最初のバージョンを非常に速く記述できます。後で最適化したいときには、どこに注意を向けるべきかを教えてくれる非常に優れたプロファイラーがあります。必要に応じてインライン バイト コードを記述して、内部ループを驚くほど高速に作成することもできます。

学習に役立つ優れた例がたくさんあり、言語は直感的なので、例から数分で使い方を習得できます。マニュアルをあまり見る必要はありません。マニュアルは薄く、警告や制限事項もほとんどありません。

この言語には、コアが小さく、強力で、高度に直交するライブラリがあり、コア言語と同様に注意深く設計されています。ライブラリはすべて連携して動作し、言語内のすべてが、高級カメラの部品のようにぴったりとフィットします。非推奨のものや、互換性のために保持されているものはありません。すべてのライブラリのソース コードはすぐに入手できます。オペレーティング システムや他の言語で記述されたアプリケーションと簡単に通信できます。

この言語はレイヤーで構築されています。高レベルの抽象化は、低レベルの抽象化から非常に透過的な方法で構築されており、必要に応じて取得できます。

絶対に隠す必要がないものは、何も隠していません。この言語は、何をすべきかを指示する手段としてではなく、作業の節約の手段としてのみ抽象化を提供します。実際、この言語は、設計に平等に参加することを奨励しています。構文を含め、言語のすべてを変更できます。また、記述したものはすべて、可能な限り、定義済みのものと同等のステータスになります。

注記

[1] 現代のアイデアに非常に近いマクロは、Lisp 1.5 がリリースされてから 2 年後の 1964 年に Timothy Hart によって提案されました。当初欠けていたのは、変数のキャプチャと多重評価を回避する方法でした。Hart の例は、その両方に該当します。

[2] *『空気が脳に当たるとき』の中で、*脳神経外科医のフランク・バートシックは、チーフレジデントのゲイリーが外科医と内科医(「ノミ」)の違いについて語った会話を詳しく述べています。

ゲイリーと私は大きなピザを注文し、空いているブースを見つけた。チーフはタバコに火をつけた。「あの忌々しいノミどもを見てみろ、一生に一度しか見ない病気についてペラペラしゃべってる。それがノミの厄介なところだ。彼らは奇妙なものしか好きじゃない。彼らはパンとバターのケースを嫌う。それが我々とクソノミの違いだ。我々は大きくてジューシーな腰椎椎間板ヘルニアが大好きだが、彼らは高血圧を嫌う…」

腰椎椎間板ヘルニアをジューシーと考えるのは難しい (文字通りでない限り)。しかし、私は彼らの言っている意味は理解していると思う。私はジューシーなバグを何度も追跡してきた。プログラマーでない人にとっては、バグに喜びがあるとは想像しにくいだろう。確かに、すべてがうまく機能する方が良い。ある意味ではそうである。しかし、ある種のバグを追い詰めることには、間違いなく陰鬱な満足感がある。