Paul Graham, May 2001.
Copyright 2001 by Paul Graham
これは、Paul Graham: Being Popularを、原著者の許可を得て翻訳・公開するものです。
プロジェクト杉田玄白正式参加テキスト。
<版権表示>
本和訳テキストの複製、変更、再配布は、この版権表示を残す限り、自由に行って結構です。
(「この版権表示」には上の文も含まれます。すなわち、再配布を禁止してはいけません)。
Copyright 2001 by Paul Graham
原文: http://www.paulgraham.com/popular.html
日本語訳:Shiro Kawai (shiro @ acm.org)
<版権表示終り>
文中、Eric Raymondの "How to become a hacker" からの引用部分の訳は 山形浩生氏の訳を 引用させていただきました。
Paul Graham氏のエッセイをまとめた『ハッカーと画家』の
邦訳版が出版されました。
出版社の案内ページ
Amazon.co.jp
サポートページ
2001/12/9 翻訳公開
Osamu NAKAMURAさんより誤記の訂正を頂きました。多謝。
2002/6/10 プロジェクト杉田玄白正式参加に伴い版権表示を整備
2002/9/16 森 雄一郎さんより誤記の訂正を頂き、反映。
2004/3/18 HIRAUCHI Hideyukiさんより誤記の訂正を頂き、反映。
この記事は、新しいLispのための一種のビジネスプランとしてまとめたものである [訳注0]。 従って、良いプログラミング言語の最も重要な機能である、強力な抽象化機能という点は 省いてある(当然備えているべきものだからだ)。 Copyright 2001 by Paul Graham, 2001年3月公開、2001年4月改訂。
友人がかつて、著明なオペレーティングシステムの専門家に、 本当に素晴らしいプログラミング言語を設計したいんだと話したことがある。 専門家は、それは時間の無駄だよと答えた。プログラミング言語に 人気が出るかどうかはその言語の良さとは関係がない、 だからいかに良い言語を作ろうと誰も使ってはくれないよ、と。 少なくとも、それが彼がかつて設計した言語に起こったことだった。
何がある言語を人気のあるものにするのだろう? 人気のある言語はその人気に見合っているのだろうか。 良いプログラミング言語というものを定義する試みに意味はあるだろうか。 どうやればそれができるだろうか。
これらの質問の答えは、ハッカーを観察し、彼等が何を欲しているかを学ぶことで 得られると私は考える。プログラミング言語はハッカーのものだ。 プログラミング言語は、ハッカーに好まれてこそプログラミング言語たることができる。 そうでなければ表示意味(denotational semantics)やコンパイラ設計の単なる練習課題にすぎない。
確かに、大抵の人々はプログラミング言語を、その利点だけを見て選ぶことはしない。 プログラマの多くは誰か他の人から使うべき言語を指示される。それでも、そのような外部の 要因がプログラミング言語の人気に及ぼす影響は、普通に考えられているほど 大きくないと私は思う。むしろ大きな問題は、ハッカーが考える良いプログラミング言語 というものと、多くの言語設計者が考えるそれとが同じでないことだ。
ハッカーと言語設計者では、重要なのはハッカーの意見の方だ。プログラミング言語は 定理のためにあるんじゃない。それは道具であり、人々のために設計されるべきだ。 靴が人間の足のためにデザインされるのと全く同様に、人間の強さと弱さに 合致するようにデザインされなくちゃならない。 彫刻作品と見まがうほど優美な概観を備えていようと、 履いたら足が痛くなるようなら、それは悪い靴でしかない。
プログラマの大部分は良い言語と悪い言語の区別がつかないのかもしれない。 が、それは他の道具とて同じことだ。多くの人に見分けがつかないからといって 良い言語を設計しようとすることが時間の無駄になるなんてことはない。 優れたハッカー は良い言語を見ればそれとわかるし、それを使おうとするはずだ。 優れたハッカーはごく少数派ではあるが、その少数の人々が優れたソフトウェアを 生み出し、残りのプログラマがどの言語を使うかに影響を与えて行くのだ。 実際のところ、それは影響じゃなくて命令になる場合だってある。優れたハッカーは 上司や教員として、他のプログラマにどの言語を使うか指示する立場にいることが多いからだ。
優れたハッカーの意見だけがプログラミング言語の相対的な人気を決めるわけではない。 過去の遺産(Cobol)や大げさな宣伝(Ada, Java)ももちろん影響する。 だが、長期的な影響力としてはやはり優れたハッカーの意見が最も強力だと私は考える。 臨界点となる初期ユーザ層と十分な時間があれば、プログラミング言語はその力に相等しい 人気を得ることができるはずだ。そして、人気が出れば出る程良い言語は悪い言語との 差を拡げて行く。現実の、生きたユーザからのフィードバックが常に発展を促すからだ。 人気のある言語がいかに変化していったかを見たまえ。PerlとFortranが最も 極端なケースだが、Lispでさえ大きく変化したのだ。例えば Lisp1.5はマクロを持っていなかった。MITのハッカー達が本物のプログラムを 書くためにLispを2年ほどいじった後でマクロは追加されたのだ [1]。
したがって、人気が出るためには良い言語でなければならないかどうかはともかくとして、 良い言語であるためには人気がなければだめだ。そして、良い言語で有り続けるためには 人気があり続けなければならない。最先端のプログラミング言語はじっとしていない。 こんにちのLispは1980年代中頃にMITにあったものからたいして変化していないが、 それはその時代を最後にLispは発展に必要な大きさのユーザベースを失ったからだ。
もちろん、ハッカーは言語を使うまえにそれを知らなければならない。どうやって 彼等は新しい言語を知るのだ? 他のハッカーからだ。 だがそれには、いちばん最初にその言語を使い始めるハッカー達がいなければならない。 この最初のハッカー達のグループはどのくらいの大きさだろう。臨界点となる ためには何人くらいのユーザが必要だろう。私の頭にぱっと浮かんだ答えは、20人だ。 もし言語に20人の独立したユーザ、つまり自分でその言語を使うと決めたユーザが いれば、私はその言語が本物だと考える。
そこに至るのは簡単ではない。0から20に至るのは、おそらく20から1000に至るのより 難しいだろう。最初の20人を獲得する最も良い方法はトロイの木馬だ。 人々の欲するアプリケーションを、たまたまその言語で書いて提供するのだ。
まず、プログラミング言語の人気に確かに影響を与える一つの外部要因を 認めることから始めよう。人気が出るためには、プログラミング言語は 人気のあるシステムのスクリプト言語でなければならない。FortranとCobolは 初期のIBMメインフレームのスクリプト言語だった。CはUnixのスクリプト言語だったし、 後にPerlがそうなった。TclはTkのスクリプト言語だ。JavaとJavascriptは webブラウザのスクリプト言語として考えられた。
Lispは残念ながらものすごく人気のあるシステムのスクリプト言語では無く、 したがってものすごく人気のある言語に成り得ていない。現在のLispの人気は、 LispがMITのスクリプト言語であった1960年代と1970年代の頃の名残りでしかない。 当時の多くの偉大なプログラマはどこかでMITとつながっている。 そして1970年代の初期、Cの前に、MITのLisp方言であるMacLispは 真剣なハッカーが使いたがる唯一の言語であった。
こんにちでは、Lispはやや人気のある二つのシステム、EmacsとAutocadの スクリプト言語である。おそらく、今日のLispプログラミングの大部分はEmacs Lisp とAutoLispで行われているだろう。
プログラミング言語は孤立しては存在しない。「ハックする」は他動詞だ--- ハッカーはふつう何かをハックする---そして現実にはプログラミング言語は それを使って何をハックするかによって判断される。だから人気のある言語を 設計しようと思ったら、言語以上のものを提供するか、既にあるシステムの スクリプト言語を置き換えるかしなくちゃならない。
Common Lispに人気が出ない理由のひとつは、それが孤児だからだ。 Common Lispはもともとはそれでハックするシステムから生まれた:Lisp Machineである。 しかし、Lisp Machine は (並列計算機と共に)、1980年代の汎用プロセッサの 増大するパワーによってぺしゃんこにされてしまった。Common LispがUnixの良い スクリプト言語であればまだ人気を保っていたかもしれないが、 残念ながらCommon Lispはスクリプト言語としては猛烈にひどい出来だ。
この状況を以て、言語はその利点では判断されないと言うこともできるだろう。 別の見方として、プログラミング言語は何かのスクリプト言語でなければ真のプログラミング言語 になれないということもできる。このことに今気付いた人にとっては、 これはアンフェアに思えるかもしれない。 私は、それは、プログラミング言語には実装が伴っていなければならない というのと同じようなものだと思う。 それはプログラミング言語というものの一部なのだ。
もちろん、プログラミング言語は良い実装を必要とするし、しかもそれはフリーで なければならない。会社はソフトウェアに金を払うだろうが、個々のハッカーは 払わない。そして今惹き付けたいのはハッカーなのだ。
また、言語はそれについて書かれた良い本を必要とする。その本は薄くてうまく書かれていて、 また良い例がいっぱい詰まっていなければならない。K&Rは理想的だ。 現時点で言うなら、言語にはオライリーから出版された本が無ければならない とも言えるだろう。それはハッカーの関心を得るテストになりつつある。
オンラインドキュメントも必要だ。実際、本は最初はオンラインドキュメントとして 書かれ始めたっていい。だが物理的な本の必要性はまだ無くなっていないと思う。 物理的な本は便利だし、完璧ではないにせよ出版社を通ったということである程度の質は 保障される。本屋は依然として新しい言語を学ぶのに最も重要な場所だ。
どんな言語にも必要な3つの要素---フリーの実装、本、そしてハックすべきもの--- が揃ったとして、さてどうやって言語をハッカーの好むものにできるだろう。
ハッカーが好む要素のひとつは簡潔さだ。 ハッカーは怠惰だ。数学者や現代建築家が怠惰であるのと同じように。 余分なものは嫌われる。これからプログラムを書こうとしているハッカーは少なくとも無意識的に 予測される総タイプ量によってプログラミング言語を選んでいる、と言っても、 真実からそれほど遠くはあるまい。これがハッカーの考える方法と正確に 一致していないとしても、言語設計者はそう仮定することでうまくやれるだろう。
英語に似せた長くてごちゃごちゃした表現でユーザを子供扱いするのは間違いだ。
Cobolはこの欠陥によって悪名が高い。
ハッカーは、
z = x + y
と書く代わりに
add x to y giving z
と書けなんて言われたら、良くて彼の知能への挑戦、悪くて神をも怖れぬ大罪だと
思うだろう。構文は重要なのだ。
プログラムを読みやすくするために、 Lispはcarとcdrの代わりにfirstとrestを使うべきだとしばしば言われて来た。 ま、最初の2時間くらいはそうかもしれない。だがハッカーは、carはリストの最初の 要素でcdrは残りの要素だなんてことくらいすぐに覚えられる。firstとrestは 50%もタイプ量が多い。それにfirstとrestじゃ長さが違うから、 並べて使われた時にcarとcdrのように引数が綺麗に並ばない。 ページ上でどうコードが並ぶかというのは重要だと私は経験から知った。 可変幅のフォントで表示されたLispコードを私はほとんどまともに読めないし、 私の友人達はそれは他の言語でも同様だと言う。
簡潔さという点では、強力に型付けされた言語は負ける。 他の条件が同じなら、誰もたくさんの宣言の並びからプログラムを書き始めたいとは 思わない。暗黙にできることは暗黙になっているべきだ。
個々の語句も短いほうが良い。PerlとCommon Lispはこの点で両極端にある。 Perlのプログラムはほとんど暗号とも呼べる程に詰まっており、 一方でCommon Lispの組み込みオペレータの名前は滑稽な程に長い。 Common Lispの設計者は、言語のユーザはそういう名前を自動的に補完してくれるような エディタを使うことを前提にしていたのかもしれない。 しかし、長い名前が問題になるのは書くときだけじゃない。 読むときにもコストがあるのだ。長い名前はより大きなスクリーン上のスペースを 占有する。
ハッカーにとって、簡潔さより大事なことがある。自分のやりたいことがやれることだ。 プログラミング言語の歴史をふりかえってみると、「正しくない」と考えられる 行いをプログラマがするのを防ぐために驚くべき程の努力が払われて来た。 これは危険なほどにおこがましい計画である。プログラマが必要とするであろうことを、 どうやって言語設計者はあらかじめ知ることが出来ると言うのだ? 言語設計者は、ユーザを自分のミスから守ってやらなきゃならないようなまぬけではなく、 設計者が考えもしなかったようなことを実現できる天才と考えた方が良いと思う。 何をしようがまぬけは自分の足を撃つのだ。他のパッケージの変数を参照するミスを 防いでやることはできたとしても、問題設定を間違えた悪い設計のプログラムを 延々と書き続けることから救うことはできない。
良いプログラマはしばしば危険で不道徳なことをしたがる。 不道徳とは、ここでは言語が呈示しようとしている意味構造の裏口を覗くような行為だ。 高レベルの抽象化されたデータの内部表現をいじってみるようなことだ。 ハッカーはハックするのが好きで、ハックというのはそもそも物事の内側に 入り込んでもとの設計者を後知恵で批判するようなものだからだ。
後から批判され修正されることを恐れるな。どんなツールでも、人々はもとの 設計者が意図しなかったように使うものだし、プログラミング言語のように明確な 意図のあるものではとくにそうだ。たくさんのハッカーが、あなたが想像だにしなかった方法で 意味論的モデルをいじりたがるだろう。そうさせよう。 ガベージコレクタのようなランタイムシステムを危険にさらさないぎりぎりのところまで、 内部にアクセスできるようにしておこう。
私はCommon Lispでしばしば構造体のフィールドをループしたいと思うことが あった。例えば削除されたオブジェクトへのリファレンスを抜きだしたり、 初期化されていないフィールドを見つけたりするようなことだ。 構造体が内部では単なるベクタで表現されていることを私は知っている。 それでも私はどんな構造体に対しても呼べる汎用関数を書くことができない。 構造体のフィールドには名前でしかアクセスできないからだ。 それがそもそも構造体の意図するところだからだ。
ハッカーが大きなプログラムの中で意図されたモデルを破りたいと思うのは 多分1箇所か2箇所くらいのものだろう。それでも、それがどんなに大きな違いを もたらすことか。そして、それは単に問題を解決できるというだけじゃない。 そこには一種の快感が潜んでいる。外科医がぞっとするような内臓をのぞき込む時の 密かな快感[2]や、ティーンエイジャーがニキビを潰す時の密かな快感と同じだ。 少なくとも男の子にとって、ある種の恐怖は魅力的だ。雑誌Maximは 毎年ピンナップとぞっとするような事故の写真を集めた写真集を発刊している。 彼等は自分達の客を良く分かっている。
歴史的に、Lispはハッカー達に内部をいじくるらせるのがうまかった。 Common Lispの政治的に正しくあろうとする態度の方が邪道なのだ。 初期のLispは何でもありだった。幸いなことに、マクロには その精神の多くがまだ残されている。ソースコードを好きなように変換できるという ことの何と素晴らしいことか。
クラシックなマクロは本物のハッカーの道具だ---簡単で、強力で、危険だ。 それが何をするかを理解するのはあまりに容易だ。マクロの引数を以て関数を 呼び出し、それが返したものをマクロ呼び出しがある場所に挿入する。 健全なマクロは全く反対の原理を表明している。それがやっていることを理解するのを 妨げているのだ。健全なマクロを一つの文で説明したものを見たことがない。 健全なマクロはプログラマの望むところを規定しようとする危険な思想の 古い例である。健全なマクロは、他のいくつかのことと共に、 変数の捕獲から私を守ってくれるが、変数の捕獲こそが私がマクロでやりたいことの 一つなのだ。
本当に良い言語は、綺麗でかつ汚くあるべきだ。綺麗にデザインされ、 直交性の高いオペレータと良く理解された小さなコアで構成され、 しかしハッカーが好きなことをできるような汚さを備えている。 Cがこれに当てはまる。初期のLispもそうであった。 本当のハッカーの言語は多少野卑な性質を持っているものだ。
良い言語は、「ソフトウェア工学」なんて言葉を使うような人々が こりゃダメだと頭を振るような機能を持っているべきだ。その対極にある 言語はAdaやPascalのようなもので、礼儀正しくて教育には適しているが 他のことにはあまり使えない。
ハッカーを惹き付けるには、言語はハッカーが書きたがるようなプログラムを 書くのに適していなければならない。それは、意外かもしれないが、 書き捨てのプログラムを書くのに適していなければならないということだ。
書き捨てのプログラムとは、限定された仕事をするために手早く書き上げる 類のプログラムのことだ。何かのシステム管理の仕事を自動化したり、シミュレーションの テストデータを生成したり、データのフォーマット変換をするような。 このような書き捨てのプログラムに関する意外な事実とは、第2次大戦中に 多くのアメリカの大学で建設された「一時的な」ビルディングのように、 それがしばしば捨てられずに使われ続けることである。 たくさんのそういったプログラムは本物のユーザと本物の機能を得て、 本物のプログラムへと進化してゆく。
私は、最良の大きなプログラムは、フーバーダムのように最初から大きく設計されるのではなく、 書き捨てのプログラムから生まれるんじゃないかという気がしている。 ゼロから巨大なものを建設するのはおっかないことだ。巨大すぎるプロジェクトに 取り掛かるとき、人々は圧倒される。そんなプロジェクトは泥沼にはまるか、 貧弱で気の抜けた結果しか出さない。本物のダウンタウンの代わりにショッピングモール になったり、ローマではなくブラジリアになったり、CではなくAdaになったり。
大きなプログラムを書く別の方法は、書き捨てのプログラムから始めて 改善し続けることだ。このアプローチは気力をくじくことがないし、 進化することでプログラムの設計を良くして行くことができる。 見回してみれば、多くの大きなプログラムはこのようにして作られて来た。 そしてこの方法で進化を遂げたものは、依然としてそれが最初に書かれた言語で書かれているだろう。 プログラムが他の言語に移植されるなんて、政治的な理由でもなけりゃ起こらないからだ。 従って、逆説的であるが、もし大きなシステムで使われる言語を作りたいと思うなら、 書き捨てのプログラムを書くのに良い言語にしなくちゃならない。大きなシステムは そこから始まる。
Perlがこのアイディアの最も印象的な例であろう。Perlは書き捨てのプログラムの ために設計されたというだけでなく、Perl自身が書き捨てのプログラムのようなものだった。 Perlはレポートを生成するためのユーティリティのコレクションとして産声を上げ、 人々が書く書き捨てのプログラムが大きくなってきてからプログラミング言語へと進化した。 Perl 5になってようやく重要なプログラムを書くのに相応しい言語になったが、 既にその時には非常にポピュラーになっていたのだ。
書き捨てのプログラムを書くのに良い言語とはどういうものだろう。 まず、それはいつでも使える状態になければならない。書き捨てのプログラムとは あなたが1時間かそこいらで書きたいと思うものだ。だからその言語は既に あなたのマシンにインストールされていなければならないだろう。 使う前にわざわざインストールしなくちゃならないんじゃだめだ。そこに無いと。 Cはそこにある。OSについてくるからだ。Perlもそこにある。もともと システム管理のためのツールで、それゆえに既にインストールされていることが多いからだ。
しかし、使える状態にあるとは、インストールされているというだけではない。 コマンドラインインタフェースを持つ会話的な言語の方が、いちいちコンパイルと 実行をわけなくちゃならない言語より使える。人気の出るプログラミング言語は 会話的でなければならず、しかも素早く立ち上がらなくちゃならない。
書き捨てのプログラムに必要なもうひとつのことは、簡潔さだ。 簡潔さは常にハッカーを惹き付けるが、1時間で書き上げたいと思う ようなプログラムではなおさらだ。
もちろん、究極の簡潔さとは、欲しいプログラムが既に書かれていてそれを呼ぶだけ、 というものだ。そこで、私がプログラミング言語の中でますます重要になってゆくと 思われることに話を移そう。ライブラリ関数だ。Perlは文字列操作の豊富なライブラリ のおかげで人気が出た。このクラスのライブラリは書き捨てのプログラムでは とくに重要だ。データを変換したり取り出したりするものが多いからだ。 たくさんのPerlプログラムは、最初はいくつかのライブラリコールをつなぎ合わせただけの ものから始まるだろう。
この先50年のプログラミング言語の進化は、ライブラリ関数に関するものに なるだろうと思う。未来のプログラミング言語は、言語のコアと同じくらい慎重に 設計されたライブラリを備えているだろう。プログラミング言語の設計の重点は、 強い型付けにするか弱い型付けするかとかオブジェクト思考にするかとか 関数型にするかとかそういうことではなく、どうやったら素晴らしいライブラリを 設計できるかということになってゆくだろう。型システムの設計みたいなことを考えるのが好きな 言語設計者は身震いするかもしれない。ライブラリの設計だなんて、 アプリケーションを書くみたいなことじゃないか! 残念でした。 言語はプログラマのためのもので、プログラマが必要としているのは ライブラリなのだ。
良いライブラリを設計するのは難しい。たくさんのコードを書けば良いというものでは ない。ライブラリが大きくなりすぎると、必要な関数を探し回るより自分で 書いてしまった方が早いなんてことが起こる。ライブラリは、コア言語と同様に、 小さな直交性の高い操作を使って設計されなければならない。 プログラマが、どのライブラリが欲しい機能を実行できるかを推測できるように なっていなければならない。
ライブラリは、Common Lispが失敗した点のひとつだ。文字列操作にはごく 原始的なライブラリしかないし、オペレーティングシステムにアクセスするものは ほとんど皆無だ。歴史的な理由から、Common LispはOSなんて存在しないかのように ふるまってきた。だがOSにアクセスできないということは、Common Lisp組み込みの オペレータだけではまともなプログラムは書けないということになる。 実装に依存する何らかのハックをつかわなくちゃならないだろう。 そして、そういうハックはあなたの欲しいものを全ては与えてくれない。 Common Lispに強力な文字列ライブラリと良いOSインタフェースがあったなら、 ハッカーはLispをもっと好んでいただろう。
Lispの構文を持つ言語、もっと正確に言えば構文を持たない言語は ポピュラーになれるだろうか? この問題の答えを私は知らない。 私が考えるのは、Lispが現在ポピュラーでない主要な理由はその構文ではないという ことだ。Common Lispは、見慣れない構文よりもっと悪い問題を抱えている。 前置構文を使いこなせるプログラマでも、強力な文字列処理とOSインタフェースの ためにPerlの方を使う、という例を私はいくつか知っている。
前置記法には2つばかり問題があるかもしれない。プログラマにとって 馴染みが少ないということと、密度が高くないということだ。 Lispの世界の伝統的な解釈では最初の問題こそが真の問題とされていた。 だが本当にそうだろうか。確かに前置記法は普通のプログラマを狼狽させる。 だが、普通のプログラマの意見は重要じゃない。優れたハッカーがどう考えるかが 言語の人気を決めるのだ。Perlの構文はほとんど理解不能だが、それがPerlの人気の 足を引っ張っているとは思えない。Perlが備えているそういう性質はむしろPerl信者を 元気づけてきたのだ。
より深刻な問題は、前置記法の散慢さだ。 優れたハッカーにとってはこれが本当の問題だ。誰も、a[x,y]と 書けるところを(aref a x y)と書きたいとは思わない。
この特定の例に関しては解決策がある。データ構造を、インデックスが渡された時は 関数であるかのように振舞わせれば、(a x y)のように書くことができて、 これはPerlの書式よりも短い。他の式も似たようなトリックを使って短くできるだろう。
インデントに意味を持たせれば、たくさんの括弧を取り除くか省略可能にできる。 プログラマがコードを読む時は結局インデントを見ているのだ。インデントの示す 構造とデリミタの示す構造が食い違っている場合、我々は大抵インデントの方を見てしまう。 インデントに意味を持たせれば、このようなよくあるバグの元を減らせると共に、 プログラムを短くできる。
中置記法は確かに読みやすい。とくに数式ではそうだ。私はプログラマのキャリアとして ずっとLispを使ってきたが、それでも前置記法による数式が自然であるとは思えない。 だがそれは便利なのだ。特に可変長引数を取るオペレータを使うコードを生成するような場合にだ。 もし中置記法を採用するなら、リーダーマクロの一種として実装するのが良いだろう。
Lispに構文を持ち込むことに対して宗教的な反発を感じるべきではないと思う。 少なくともその構文が、ベースとなるS式へとよく理解された方法で変換されるならば。 既にLispには結構な量の構文が持ち込まれているのだし、その使用を強制しないのであれば さらに構文を追加しても悪いことはなかろう。Common Lispではいくつかのデリミタは 言語に予約となっているから、少なくとも設計者の一部は将来もっと多くの構文を 追加することを意図していたのだろう。
Common Lispの中で、言語道断にLispらしからぬ構文はformat文字列にある。 formatはそれ自身の言語を持っており、それはLispではない。Lispに更に構文を 追加するならformat記述子もそれに含めるべきだ。マクロが他のコードを生成するのと 同じようにformat記述も生成できたら良い。
ある非常に優れたLispハッカーが、彼のCLtL [訳注1] はformatのところで開く癖がついてしまったと私に語ったことがある。 実は私のもそうだ。多分これは改善すべき箇所を暗示している。 また、プログラムはI/Oをたくさんするものだということも意味している。
皆知っているように、良い言語は速いコードを生成しなければならない。 しかし現実には、言語設計において速いコードを出すことが最優先されるべきとは 思えない。Knuthがずっと昔に指摘したように、速度は重要なボトルネックとなる 箇所のみで問題となる。そして、たくさんのプログラマが経験していることだが、 どこがボトルネックかを読み違えるのは非常に良くある間違いだ。
従って、速いコードを得る現実的な方法は、言語を強い型付けにしたりする ことじゃなく、非常に良いプロファイラを作ることだ。プログラム中の全ての 関数の全ての引数の型を知る必要なんてない。ただ、ボトルネックとなるところの 引数の型を宣言してやる必要はある。そうするには、どこがボトルネックかを 知る必要がある。
Lispに関して言われ続けて来た不満は、何が高価な操作かを知るのが難しいという ものだ。これはおそらく真実だろう。だが、高度に抽象的な言語を持つ以上 それは避けがたいことでもある。そして、良いプロファイリングこそが 問題を解決する正しい道だと私は考える。何が高価かはそれで知ることができる。
この問題の一部は社会的なものだ。言語設計者は速いコンパイラを書きたがる。 だってそれが彼等の技術を示すものだから。彼等にとっては、プロファイラは 眼中にあったとしても附属品にすぎない。だが現場では、実際のプログラムを 改善するには速いコードを出すコンパイラよりも良いプロファイラの方が役に立つ。 ここでも、言語設計者はそのユーザから乖離している。 彼等は問題を解決するために素晴らしい仕事をしているが、その問題は 現場の問題とちょっとばかりずれているのだ。
アクティブプロファイラ---プログラマが尋ねた時だけでなく、パフォーマンス データを常にプログラマに示してくれるようなプロファイラ---は良いアイディアかも しれない。例えばプログラマがソースを編集するときに、エディタはボトルネックを 赤く表示するといった具合だ。別のアプローチは、走っているプログラムの 中で起こっていることを何らかの方法で表現することだ。サーバーベースのアプリケーション ではこれは特に役に立つだろう。たくさんの走っているプログラムを見ていなければ ならないからだ。アクティブプロファイラは走っているプログラムのメモリの アクセス状況をグラフィカルに表示したりとか、音で知らせるとかできるかもしれない。
音は問題を知らせる良い合図だ。私がかつて仕事をしたところでは、 Webサーバの状態を見せるメーターのついた大きなボードがあった。 何かあると、メーターの針が小さなサーボモーターで動かされるのでちょっとした 音を立てる。私の席からはそのボードは見えなかったのだが、音だけで サーバーに問題が生じた時はすぐにわかった。
効率の悪いアルゴリズムの箇所を自動的に検出するプロファイラを書くことさえも 可能かもしれない。ある種のメモリアクセスのパターンが悪いアルゴリズムのサインだと 聞いても私は驚かない。コンピュータの中に我々のプログラムを実行してくれるこびとが 走り回っているとしたら、彼は連邦政府の雇用者が語るのと同じくらい、彼の仕事の どこがどれだけ非効率かを語ってくれるだろう。私はよく、今自分はプロセッサに 野生のがちょうを追っかけさせるようなことをしているんだろうなと 感じることがあるが、実際に何がどうなっているのかを見る良い方法は無かった。
多くのLisp処理系はバイトコードにコンパイルしてそれをインタプリタで実行する。 これは移植を簡単にするために行われることが多いが、言語の機能としても有用かもしれない。 バイトコードを言語のオフィシャルな定義の一部としてしまって、プログラマが ボトルネックの部分ではバイトコードをインラインで書けるようにするのだ。 そうすればそういう最適化さえも移植可能になる。
エンドユーザが感じるアプリケーションのスピードの性質は変化してきている。 サーバーベースのアプリケーションが増えるにつれ、プログラムはI/Oに律速される ことが多くなって来た。I/Oを速くすることには価値があるだろう。 言語は、単純にフォーマット出力を速くすることによっても、 またキャッシュや永続オブジェクトのような深い内部構造の変更によっても これをサポートすることができる。
ユーザはレスポンスタイムに関心がある。しかし、もうひとつの効率の指標が重要に なってきている。プロセッサ当たりのサポート可能なユーザ数だ。 近い将来、たくさんの興味深いアプリケーションがサーバーベースで書かれるように なるだろう。そのようなアプリケーションをホストする立場で最も重要なのが サーバー当たりどれだけのユーザを受け付けられるかという点だ。 サーバーベースのビジネスの総コストに対して、その値は分母に効いて来る。
長い間、エンドユーザ向けのアプリケーションにとって効率はあまり重要ではなかった。 開発者は、いつでもユーザはより強力なプロセッサを手に入れてゆくことを当てにできた。 そしてパーキンソンの法則により、ソフトウェアはそこにある資源を使い尽くすように 拡大する。サーバーベースのアプリケーションではこの流れは変わるだろう。 そこでは、ハードウェアとソフトウェアはセットで提供される。 サーバーベースのアプリケーションを提供する企業は、サーバー当たりのユーザ数の 違いによって大きな差がつくだろう。
ある種のアプリケーションでは、プロセッサが律速となり、実行速度の最適化が 主要な課題となるだろう。だが、メモリが律速となることも多い。同時接続ユーザ数は 各ユーザのために必要なメモリ量でも決って来る。ここでも言語が助けになる可能性がある。 良いスレッドのサポートがあれば、全てのユーザが一つのヒープを共有することも 可能かもしれない。永続オブジェクトのサポートや、言語レベルでの遅延ロードなども 助けになるだろう。
人気のある言語が必要とする最後の成分は時間である。 誰も、消えてしまう言語でプログラムを書きたいとは思わない。 そしてたくさんの言語が現われては消えて行く。大抵のハッカーは、 言語が作られてから最低でも2年間くらい経ってようやく、 それを使うことを考え始める。
新しい素敵なものを考え出す発明家はしばしば見落とすのだが、 人々にメッセージが行きわたるには時間がかかるのだ。私のある友人は 誰かに何かを頼まれても、一回目は何もしようとしない。 人々はよく何かを思い付きで頼んで、後からそれが不要だったとわかることが 多いと彼は知っているからだ。時間を浪費しないために、彼は3回か4回目の リクエストが来るまで待つ。そのころにはリクエストを出した人はかなり いらついているが、少なくともその人はそれが本当に必要だということがわかっている。
大抵の人は、耳にする新しいことに対して、似たようなフィルタを身につけている。 何かを10回は耳にするまで、人々はそのことに注意を払おうとさえもしない。 これは全く正当なことだ。新しくてホットなんとやらの大部分は時間の無駄で、 消えていってしまうものだからだ。私自身、VRMLを学ぶのを遅らせることで それを学ぶことそのものを避けることができた。
したがって、何か新しいものを発明した人は、人々がその価値に気付くまで、 何年も根気良くメッセージを繰り返すことを覚悟しておかねばならない。 我々は、私の知る限りでは最初のウェブサーバーベースのアプリケーションを 書いたが、人々がそれを使うのに何もダウンロードする必要が無いと納得するまでに 何年もかかったのだ。人々が間抜けだったわけではない。彼等は、我々にメッセージを 届けさせたのだ。
この事実の良い面は、単純な繰り返しで解決できることだ。 とにかく自分の伝えたいことを話し続ければ、いずれ人々は耳を傾けてくれるようになる。 人々があなたに注意を払うのは、あなたがそこに居ることに気付いた時じゃなく、 あなたがまだそこに居ることに気付いた時だ。
また、勢いを得るまでにも時間がかかるのが普通だ。 多くの技術は最初に発表された時から大きく発展を遂げるものだし、プログラミング言語では 特にそうだ。新しい技術にとって一番良いことは、最初に採用してくれる 少数の人々によって2〜3年間使われることだ。最初に使ってくれる人々は 知識があり要求も高く、あなたの技術に残っている欠点を速やかに洗い流してくれる。 また、ユーザが少数であればあなたは彼等全員と緊密にコンタクトが取れる。 最初に使ってくれる人達は、あなたがシステムを改善することには、 それが既存のシステムを動かなくするものであったとしても寛容だ。
新しい技術を紹介するには二つの方法がある。有機的に成長する方法と、 ビッグバンみたいな方法だ。有機的な成長は、低予算のガレージベンチャーに実例を 見ることができる。誰にも知られずひっそりと、2人ばかりの若者が、新しい技術を 創り出す。彼等はそれをマーケティングも無しに発表し、最初はごく少数のユーザしか 得られない(でもそのユーザはその技術の熱狂的なファンだったりする)。 彼等は技術を改善し続け、同時に彼等のユーザベースは口コミで広がって行く。 彼等がそれと気付く前に、彼等は大きくなっている。
もう一つのアプローチ、ビッグバン法は、ベンチャーキャピタルにバックアップされて、 派手にマーケティングされたベンチャー企業に例を見ることができる。彼等は製品を出す のを急ぎ、華々しくそれを発表して、(彼等の望みでは)直ちに大きなユーザベースを得る。
だいたい、ガレージ組はビックバン組を妬む。ビックバン組は如才なく、自信たっぷりで 出資者からも一目置かれている。彼等は何でも最上の物を手に入れられ、発表の際の 広告キャンペーンによって一躍有名人だ。有機的成長組はガレージに座って、 貧しく愛されていないと感じる。しかし、有機的成長組は自分のことをそんなふうに 考えなくても良いのだ。有機的成長はビッグバンよりも結果的に良い技術と支持者を 得ている。こんにち有力な技術を見てみれば、それらの大抵のものは有機的に 成長したものだとわかるだろう。
このパターンは企業だけでなく、後援された研究にもあてはまる。 MulticsとCommon Lispはビッグバンプロジェクトで、UnixとMacLispは 有機的成長プロジェクトだった。
「最も良い書き方は書き直すことだ (The best writing is rewriting)」 とE. B. Whiteは書いた[訳注2]。 どんな作家もこれを知っている。ソフトウェアについてもこの命題は真実だ。 デザインの最も重要な段階は再デザインである。プログラミング言語は特に 十分に再デザインされていない。
良いソフトウェアを書くには、二つの相反する考えを頭に置いておかなくちゃならない。 若いハッカーの、自分の能力に対する無邪気な信頼と、ベテランの懐疑主義だ。 「こんなの簡単だよ」と頭の半分で考える一方で、 「こんなのうまくいきっこない」と もう半分で考えるのだ。
ポイントは、実はこの二つには矛盾は無いということだ。 あなたは異なるものについてそれぞれ楽観的と懐疑的になっているのだ。 問題を解決できる可能性に関する楽観と、得られた解決の価値に対する懐疑だ。
素晴らしい仕事をする人はしばしば、自分がやっていることには価値が無いと 考えてしまう。他の人が見ればその仕事はまさに驚異的なのに、それを創った当人は 心配でいっぱいなのだ。そうなるのには理由がある。その心配こそが、 仕事を良くするものなのだ。
希望と心配のバランスをうまく取れれば、それはあなたが 二本の足で自転車をこぐように、プロジェクトを前へ押し進めてくれる。 発展の二サイクルエンジンを考えてみよう。最初のフェーズでは、自分はその 問題を解決できるという確信に押されて、あなたは狂ったように問題に取り組む。 第二フェーズでは、あなたは自分のやったことを冷たい朝日の下で眺め、 その欠陥をはっきりと目にする。だが批判的な精神が希望を押し潰さない限り、 あなたは自分のシステムが不完全であることを認め、考えるのだ。 あとこんだけ頑張ればできるかな。そしてサイクルを続けるのだ。
二つの力をバランスさせておくのは難しい。若いハッカーでは楽観主義が支配しがちだ。 彼等は何かを創り出し、それが素晴らしいものだと信じて疑わず、よりよくして行こうと 思わない。年老いたハッカーでは懐疑主義が支配し、野心的なプロジェクトに手を付けようと さえしない。
再デザインのサイクルを回し続けられるものなら何であれ良い。散文は、 作者が満足するまで何度も何度も書き直される。しかしソフトウェアは一般的に 十分に再デザインされない。散文には読者がいるが、ソフトウェアにいるのはユーザだ。 作家がエッセイを書き直したところで、古い版を読んでいた読者が 新しい版は前と互換性がなくなったから自分の考えが動かなくなったなんて 文句を言って来ることはない。
ユーザは諸刃の剣だ。彼等はあなたの言語を改善してゆく助けになるが、 同時に改善を止める要素にもなる。だからユーザは慎重に選ばなければならず、 ゆっくりと増やして行かねばならない。ユーザを持つことは最適化のプロセスとも 似ている。賢いやりかたは、それを後回しにすることだ。また、一般的なルールとして、 どんな時でも、思った以上に変更はきくものだ。変更を入れることは、 包帯をはがすのに似ている。痛みを感じたと思ったらそれはもう過去の思い出だ。
誰もが、言語は委員会で設計してはいけないと知っている。委員会は悪い設計をする。 だが私の意見では、委員会の最大の危険は、再デザインをやりにくくすることだ。 誰もが現状でどうにか満足しているときに新しい変更を入れるのには莫大な労力を要する。 委員会が決めたことは、たとえ大部分のメンバーがそれを本当は気に入ってないにしても、 そのままになりがちだ。
たった二人からなる委員会でさえ再デザインの妨げになる。別々の人が 書いた二つのソフトウェア部品のインタフェースでよくそれは起こる。 インタフェースを変更するには、両者がそれに合意して同時に変更しなければならない。 そのせいで、インタフェースは変更されずに残ることが多く、結果として どんなシステムでも後付けの問題として抱えることになる。
一つの解決法は、システムのインタフェースを水平でなく垂直に設計することだ--- モジュールが常に抽象化の階層として上下に積まれるようにする。そうすると インタフェースはモジュールのどちらかが責任を持つことになりやすい。 下のモジュールが、上のモジュールが利用する言語だとすれば、下のモジュールがインタフェースに 責任を持てるし、下のモジュールがスレーブであれば、 上のモジュールがインタフェースを支配できる。
ここまでの議論が暗示するのは、新しいLispに希望があるということだ。 ハッカーにその欲するものを与える言語なら何でも希望があるし、Lispもそれに含まれる。 Lispの奇妙さをハッカーが嫌ったと結論づけるのは間違いだったんじゃないか。 この仮説の心地よい幻覚は、我々の目をLispの本当の問題から逸して来た。 少なくともハッカーがやりたいことを駄目にするCommon Lispについてはそうだ。 ハッカーの言語は強力なライブラリとハックすべき物を必要とする。 Common Lispにはどちらも無い。ハッカーの言語は簡潔でハック可能でなくては ならない。Common Lispはそうではない。
良いニュースもある。これはCommon Lispが駄目だってことで、 Lispが駄目だってことじゃない。本物のハッカーの言語となるべき新しいLispを 作ることができれば、ハッカーはそれを使うんじゃないかと私は思う。 ハッカーはやりたいことにちゃんと使える言語なら何であれ使うだろう。 我々のやるべきことは、新しいLispがいくつかの重要な用途で 他の言語よりもうまく動くようにすることだ。
歴史が勇気を与えてくれる。次々と現われる新しいプログラミング言語は、 Lispから機能を次々と採り入れている。新しい言語がLispになるために 欠けている機能はもうあまり残っていない。最も新しいホットな言語Pythonは 中置記法を使いマクロを除いてLispを薄めたものだ。 新しいLispはこの進歩の自然な一歩になるだろう。
マーケティングのためには、新しいLispを進歩したPythonだと呼んだほうがいいんじゃないかと 考えることもある。Lispとか言うよりもずっとカッコいい。多くの人にとって、 Lispは括弧だらけの遅いAI向け言語だ。Fritz Kunzeの正式な経歴からはLの付く単語が 慎重に除かれている。 だが、新しいLispをLispと呼ぶことを恐れてはならないだろう。 Lispは未だに、最高のハッカー達---例えばコース6.001 [訳注3] を履修して理解したような人達から隠れた 尊敬を集めている。彼等こそが我々が惹き付けなければならない人々だ。
「ハッカーになるには」の中で、エリック・レイモンドはLispを ラテン語かギリシャ語のように形容している。実際には使わないかもしれないが、 教養のために学ぶべきだと:
LISPは、それをものにしたときのすばらしい悟り体験のために勉強しましょう。 この体験は、その後の人生でよりよいプログラマーとなる手助けとなるはずです。 たとえ、実際にはLISPそのものをあまり使わなくても。
私がLispを知らずにこれを読んだとしたら、質問したくて仕方無くなっただろう。 私をよりよいプログラマにしてくれるだって? (それもその後の人生で?) 言語は道具のはずだ。その言語が自分をよいプログラマにしてくれるってことは、 それが何かを意味するとしたら、その言語がプログラミングによりよいってことじゃないのか。 実際、レイモンドの言ってることは、彼自身は自覚していないかもしれないが、それを暗示している。
こんな風に思われている限りにおいては、ハッカーは新しいLispを、 たとえLispと名がついていても、受け入れるんじゃないかと思う。 但しこのLispはハッカーの言語じゃなくちゃだめだ。1970年代のLispがそうであったように。 簡潔で、単純で、ハック可能な。そして今日のハッカーがやりたいようなことを 実現する強力なライブラリを備えている。
ライブラリに関して言えば、PerlやPythonといった言語に対して彼等の土俵で 勝てる余地はあると私は思っている。これから書かれる新しいアプリケーションの多くは サーバベースのものになるだろう。 だから、新しいLispがPerlと同じくらい良い 文字列ライブラリを備え、さらにサーバベースのアプリケーションに必要な 強力なライブラリを備えていたら、それは人気が出るんじゃないか。 本物のハッカーは、難しい問題をほんの数個のライブラリコールが解決してくれるような ツールを軽蔑したりはしない。そう、ハッカーは怠惰なものなんだ。
コア言語がサーバベースのアプリケーションをサポートしていればなお良いだろう。 例えば、マルチユーザのプログラムを明示的にサポートしたり、タイプタグのレベルで データのオーナシップをサポートしたりするようなことが考えられる。
サーバベースのアプリケーションはまた、新しいLispで何をハックすべきか という質問に答えてくれる。Unixのスクリプト言語とするだけでもLispは 良いものになるだろうが(これ以上悪くするほうが難しい)、既存の言語と競争するのに 勝ちやすい領域というのはあると思うのだ。Tclのモデルをフォローするのが良いんじゃないか。 サーバベースのアプリケーションをサポートする完全なシステムを作り、Lispを それと一緒に提供するのだ。レキシカルクロージャは、UIが単なるWebページの 連なりである場合にサブルーチンの機能を提供できるし、S式はHTMLに綺麗に マップされるし、それを生成するのにマクロは最適だ。サーバベースの アプリケーションを書くのに良いツールが必要とされており、 一方新しいLispも必要とされている。この両者を一緒にやればうまく行くんじゃないか。
まとめの代わりに、ハッカーの夢の言語というのを考えてみよう。 夢の言語は美しく、明快で、簡潔だ。素早く立ち上がる 会話的なトップレベルを持つ。よくある問題を解くプログラムは ほんのわずかなコードで書ける。どんなプログラムでも、書かなくちゃ いけないのはアプリケーションに特有な部分だけだ。他の全てはあなたのために 既に作られている。
その言語の構文は極端に短い。必要のない文字をタイプする必要は ほとんどなく、シフトキーさえほとんど使わない。
高度な抽象化を使って最初のバージョンは極めて速くに書き上げられる。 後に、最適化したくなったら、非常に良いプロファイラが提供されていて、 どこに注目したらいいかを教えてくれる。必要とあらばインラインでバイトコード を書くことさえできて、内部のループを目もくらむほど速くすることができる。
学ぶためにたくさんの良い例が提供されていて、さらに言語は直観的なので 例からほんの1〜2分で使い方を学ぶことができる。マニュアルを見る必要さえあまりない。 マニュアルは薄く、注意すべき点や制限はほとんどない。
その言語は小さなコアと、コアと同じくらい慎重に設計された 強力で直交性の高いライブラリからなる。ライブラリはお互いがうまく 協調して動く。良いカメラのように、言語の全ての部分はぴったりと かみあって動くのだ。使わない方が良い機能とか、互換性のために残された 機能なんてものは無い。オペレーティングシステムや他の言語で書かれた アプリケーションとコミュニケートするのも容易だ。
その言語はいくつもの層から構成されている。抽象化の高い層は 抽象化の低い層から透過的に構成されており、必要とあらば抽象化の低い層を 直接叩くこともできる。
絶対に必要である箇所以外は、何事もプログラマから隠されてはいない。 その言語の抽象化機能は、プログラマにどうプログラムすべきかを教えるのではなく、 プログラマの仕事を楽にするためだけに提供されている。 実際、その言語はプログラマを言語の設計に参加するものとして扱い、 プログラマが書いたものは可能な限り、言語組み込みのものと同様の地位を得る。
Garyと私は大きなピザを頼んで空いている席を見つけた。 医長は煙草に火をつけると言った。「あの蚤どもを見なよ。一生に一度 お目にかかれるかどうかみたいな疾病のことばかり話している。それが あいつらの問題なんだ。珍しいものにしか興味がありゃしない。 それで食ってくような、日頃よくある症例は嫌っているのさ。 それが俺達とあの蚤どもとの違いだ。俺達はでかくて汁もしたたるような 椎間板ヘルニアが大好物だが、やつらは高血圧でさえ嫌うのさ…椎間板ヘルニアを(文字通りの意味でなく)汁もしたたるようなと形容する 感覚を理解するのは難しいが、彼等の言わんとしているところが 私には分かると思う。私もしばしば汁もしたたるようなバグを追いかけることが ある。プログラマでない人は、いったいバグにどんな喜びがあるのか 不思議でしょうがないと思う。そりゃもちろん全てがうまく動いてくれるに 越したことはない。だが、ある種のバグを追い詰めて潰した時には確かに ぞくぞくするような満足感があるものなのだ。