Lispの進化 Guy L. Steele Jr. Richard P. Gabriel Thinking Machines Corporation Lucid, Inc. 245 First Street 707 Laurel Street Cambridge, Massachusetts 02142 Menlo Park, California 94025 Phone: (617) 234-2860 Phone: (415) 329-8400 FAX: (617) 243-4444 FAX: (415) 329-8480 E-mail: gls@think.com E-mail: rpg@lucid.com 要約 Lispは世界で最も偉大な言語である - いや、支持者はそう考えている。 Lispの構造は、言語を拡張することや、何もないところから始めることなしに 完全に新しい方言を実装することさえも容易にしている。全体的に見れば、 Lispの進化は、技術的な要求のまじめな評価によってではなく、組織間の競争、 一歩先んじること、そして技術的な賢さから生まれる喜びのような"ハッカー 文化"の特質によって先導されてきた。それにもかかわらず、このプロセスは、 散らかっているがパワフルな工業用強度のプログラミング言語と、プログラミ ング理論家によって使われるのに適している小さいがパワフルな技術的に純粋 な方言の両方を、ついに産み出した。 我々は、最初のプログラミング言語の歴史(History of Programming Languages, HOPL)会議でのMcCarthyの論文が終わったところから始める。 PDP-6の時代から、InterlispやMacLispの最盛期を通り、特殊用途のLispマシ ンの上昇と下降を通りすぎ、標準化活動の現代までの発展を年代順にたどる。 それから、いくつかの著しい成功と失敗の両方を含む、Lispを他のプログラミ ング言語から区別する設計課題を明らかにするような、いくつかの代表的な言 語機能の技術的な進化を調べる。また、他のプログラミング言語を設計するた めの実験室としてのLispの使用についても議論する。Lispの進化を駆り立てた 力のいくつかの影響をもって結びとする。 イントロダクション 2 実装プロジェクト年代記 5 Lisp 1.5からPDP-6 Lispまで: 1960-1965 6 MacLisp 7 Interlisp 15 1970年代初期 21 PDP-10の逝去 22 Lispマシン 25 IBM Lisp: Lisp360とLisp370 30 Scheme: 1975-1980 32 Common Lispの前ぶれ 36 初期のCommon Lisp 36 他の普通のハードウェア方言: 1980-1984 44 標準の発展: 1984-1990 49 ある特定の言語機能の進化 60 NIL(とT)の扱い 60 繰り返し 63 マクロ 66 数に関する機能 78 いくつかの著しい失敗 81 言語の実験室としてのLisp 88 なぜLispは多様なのか 96 1 イントロダクション 1.1 この論文の構成 過去30年の間にとても多くのことがLispに起こった。年代順またはその他の 主題を通じて単一の直線を通過するのでは、全ての関心を一貫して扱うことは 不可能だとわかった。プロジェクトや方言は複雑な方法で現れ、分裂し、結合 し、そして死ぬ; 各人のキャリアは、ときには平行だが、もっとしばしば直交 的なこれらの結合を通じて織り合わされている。アイディアはプロジェクトか らプロジェクトへ、人から人へと飛びはねる。我々は、主題を通じて、断片の 列を示すことを選んだ。この構成は、必然的に、提示にいくらかの重複をもた らす。 第2節は、プロジェクトと人々の点からLispの歴史を、McCarthyが終えたと ころから[McCarthy, 1981]、IEEE, ANSI, そしてISOの中にLisp方言に対する 公式な標準を作るための努力までを議論する。第3節は、多数の技術的なテー マを調査し、それらの年代記的な進化を別々にたどる; ここでは各トピックに 対するアイディアの流れを強調する。第4節は、言語実験室や実装ツールとし ての、とりわけAI言語の開発のためのLispの使用をたどる; AI言語からのどの ようなフィードバックがLisp自身の開発に影響したかについて特別な注意を払 う。第5節は、なぜLispがそのように進化したかについてのいくつかの結論を 引き出す。 1.2 言語進化のパターン Lisp 1.5からのLispの進化は、多様化、受容、そして統合のサイクルによっ て特徴づけられる。多様化の間は、新しい言語構造、新しいプログラミングス タイル、新しい実装戦略、そして新しいプログラミングパラダイムが既存の Lisp方言で実験や導入されるか、新しいLisp方言が設計される。どちらの場合 でも、事実上、新しいLisp方言が作られる。受容の間は、これらの新しいLisp 方言は受容されるか拒絶されるかする。新しい方言の設計者または支持者は受 容のための条件を設定し、受容フェーズの成功はそれらの条件によって決定さ れるだろう。統合の間は、様々な方言は主要な方言に合併される。典型的には、 1つの方言が根として選ばれ、枝が根と同じ木か他の方言から取られるだろう。 統合は、公式または非公式の標準化のプロセスである。統合は、非常に成功し たときは、結果として安定した開発プラットフォームになる。 そのサイクルは動かし得ないものではない: そのプロセスは壊れ、停止そし て開始し得るし、サイクルはスキップし得る。しかし、進化のプロセスを、次 のステージへ移動するゴールを持つ、これらのサイクルのステージの1つの中 にあるものとして、どのような時点でも見ることが可能である。 各ステージは、そこに入ることを許す条件によって特徴づけられる。 1.2.1 受容のための条件 最も重要なステージは受容である。このステージは、どの言語機能やパラダ イムが次の安定した開発ステージの部分になるかを決定する。受容のための条 件は、正しいマシン上で、ローカルなユーザモデルにフィットし、執拗な新し い問題を解決し、正しい印を持つことである。それぞれを詳細に調査しよう。 受容ステージは、新しい方言上に仕事の基礎を置くことを選ぶ特定の受容グ ループに依存する。受容グループの一例は、営利人工知能企業から成る。特定 のLisp方言は、たとえば、主流の言語との統合を通じて、このコミュニティの 問題を解決することをターゲットとするかもしれない。この方言がサイクルの 次のステージ - 統合 - へ移動するかどうかは、この受容グループがその方言 で受容の期間に入ることを選び、その方言が実際に解決を提供することで、受 容ステージをパスするかどうかに依存する。 その方言は正しいマシン上で走るべきである。これは、正しい製造業者のマ シン上であることを含む。受容性を決定する人々が、適切な処理性能で直ちに その方言を使えるときに、Lisp方言は受容されるだろう。これは、そのマシン に対して受容可能なサイズと処理性能を持つことも含んでいる。キーになるユ ーザグループがあるサイズとスピードのコンピュータを使っている場合、その Lisp方言はそのコンフィグレーションで容認できるように走るべきである。方 言の設計者または奨励者は、ターゲットユーザ基盤にインストールされている かすぐにインストールされる、もっと限られた数のコンピュータではなく、イ ンストールされたコンピュータの総台数だけに対する目で最初のターゲットコ ンピュータをしばしば選ぶという事実により、これは複雑になる。後で見るよ うに、InterlispやNILは、それらの奨励者が間違ったコンピュータを選んだと きに使われなくなった。 次は、ローカルなユーザモデルにフィットすることである。各ユーザグルー プは、その中に新しい方言がフィットしなければならないような働き方のスタ イルまたは方法論の集合を持っている。しばしば、新しい方言は既存のものの 拡張であり、受容グループがタイムリーな仕方でその方言を受け入れることが できない限り、その方言は受容ステージに入らず、統合の部分にはなりそうに ないだろう。時々、受容グループは新たに形成され、既存の働き方のスタイル や方法論を持っておらず、その場合は新しい方言が受容グループへ受け入れ可 能な働き方のモデルを示すべきである。 次は、タイムリーな問題を解決することである。受容グループは、その方言 が受容グループによって必要とされる場合にその成功が方言の受容を決定する ようなグループである。受容グループは、新しい方言がこのステージに入ると きに処理されていないニーズの集合を持たなければならない; そうでなければ、 受容グループは新しい方言へ変更するためのニーズを持たず、おそらくこのよ うな変更はそのグループにとってあまりに危険だろう。グループが商業的であ るか、外部が決定する成功の基準の集合を持つ場合、そのグループは危険を嫌 い、新しい方言は、これらの基準を達成するためにはっきりわかる価値を提供 しなければならない。たとえば、厳しい生産性で大きなプロジェクトに投資し ていたり、要求を再利用するグループでは、強力なオブジェクト指向コンポー ネントを持つLisp方言はすぐ取り入れられるかもしれない。わずかな、あるい は漸進的な改善を持つ方言は、多くの場合受け入れられないだろう。 最後は印(cachet)である。我々は、広告やファッション業界で使われている のと同様に語`印'を使う。印のあるスカーフは、上流社会の最も高級で望まし い階層によって身につけられ、そのためスカーフは非常に望まれ欲しがられる。 印のある香水は高価であり、貴重なものとされ、人々は単に欲しいのではない - 所有したいのである。 コンピュータについてもそうである。最もよい例は - 異論がある人がいる かもしれないが - IBM PCと比べたときのMacintoshである。客観的にみると、 PC上にはかなり多くのソフトウェアがあり、業務ではMacintoshよりもおそら くずっと多く使われているだろう。しかし、Macintoshが先端のコンピュータ 人へアピールするときがある。多くのホビイスト - 偉大なコンピュータはど のようなもので、どのようにみんながそれを持つべきかについて夢中でしゃべ る人たち - をみる場合、彼らはMacintoshを持っているか、持ちたいと願って いる。PCとMacintoshの間の差は印である。 印は常に最良の種類や非常に高価、あるいは非常に高級であることを意味す るわけではない。1967年式のFord Mustangは1992年式の1992 Mercedes 300 SE よりも多くの印を持つが、後者の方がはるかに高価である。 受容グループは、個人的には新しい方言を採用したいと願うに違いない人々 から成る。Lispを使う人々は、一般に自身を先端とみなす。したがって、新し い方言の中には、少なくともなんらかの面で先端テクノロジーがなければなら ない。たとえば、CLOSはCommon Lispへ印を与える - ほとんどCLOSを持つ Common Lispを新しい方言とみなすようにしている - なぜなら、それは主流の オブジェクト指向プログラミングを超えた前進として認められるからである。 1.2.2 統合のための条件 統合とは、その間に標準 - 公式あるいは非公式の - が設定されるステージ である。ときどき、いくつかの方言が標準化プロセスや設計合理化プロセスの 組み合わせを通じて合併される。これが起こるとき、1つの方言がベースとし て普通は選ばれ、他の受容された方言からの機能が混ぜ合わされるだろう。 統合に入るための条件は、方言が受容されること、受容グループに勢いがあ ること、そして、方言が受容グループをすでに助けており、助け続けるだろう と認められていることである。 第1に、その方言が受容されなければならない。これは、その方言が、グル ープの機能的なニーズに合うだけでなく - その機能が有用である - 、グルー プの中にうまくフィットし、処理性能とサイズのゴールに合うことも含んでい る。 次に、受容グループは成長する用意が十分にできていなければならない。こ れは、Lispの方言や、おそらく他の言語の成功のための重要な外部要因である。 言語を使うだろうユーザグループは、自身が成功しているか、成功しそうだと 認められなければならない。したがって、言語は二重のハードルに直面する: 特定のグループにとって成功することと、自身が成功しようとするグループに 対してアピールすることである。受容ステージに入るための条件に結びつけら れるとき、これは、言語が正しいターゲットプラットフォームを選ぶことにも 成功しなければならないことを意味する。 さらに、受容グループが成長している、あるいは成長しようとするとき、そ のグループは、典型的にはサイズや地理的な範囲の点で成長するので、ソフト ウェア交換が重要になる。これは、受容グループが営利的でも、研究指向的で も起こる。 最後は、受容グループの成功または成功条件への、方言の認識できる貢献で ある。すなわち、受容グループは成功しているか、成功しそうだと認識される かどちらかでなければならず、方言はその状況へ貢献したように見えなければ ならない。受容グループが成功する、あるいは、方言が受容グループを現在の 位置に置いている努力に対して単に有用だというだけでは、通常は不十分であ る: 方言は、努力の必要な部分だと認識されなければならない。そうでなけれ ば、受容グループは言語決定を再評価する気になり、Lispの場合、一度この再 評価に入ると、Lispが留まることは難しい。 1.2.3 多様化のための条件 多様化は、古い解決が不十分であるか、他に何もすることがないときに起こ る。多様化に入るための条件は、外部推進要因が次第に衰えること、もっと小 さな調査開発グループへの後退があること、そして以前の方言がなんらかの点 で失敗したことである。 第1に、受容グループが下降中であるとき、言語実装改良や漸増設計に対し て割り当てるリソースは少なくなっている。言語が統合ステージを通過したと き、実装改良や設計改良を通じて漸増改良に従う: 処理性能やサイズは改良さ れ得るし、なんらかの新たな、あまり重要でない言語機能は加えられ得るが、 パラダイムシフトは多様化、受容、そして統合の新たなサイクルを必要とする。 言語のエキスパートは、これらの小さな改良を行なう義務はもはやなく、そ の代わりに、受容グループを衰退させた問題を解決することに注意を向けるだ ろう。おそらく、新しい受容グループがその問題と一緒にターゲットになる。 あるいは、おそらく他の言語が、新たな方言に組み入れるために採掘されるよ うな印や成功を持つだろう。 次に、そのような後退はもっと小さなグループ、言語グループの孤立地区を 作る。なぜなら、革新は典型的には小さなグループを巻き込み、これは新しい 設計のための事実上の必要条件である。真に重要なのは、言語設計グループが - 彼らはそのようには呼ばれないかもしれないが - 新たな設計を追求するた めに割り込みから自由であるだろうということである。 最後に、以前の解決は受容グループにとっては失敗でなければならない。た とえば、受容グループが外部の経済的な要因のために衰退する場合、変化を追 求する必要はないだろう。しかし、これは変化のための変化という意図を止め ることはなかった。これを、自分のやりかたでやった症候群(I-Did-It-My-Way syndrome)と呼ぶ人もいる。 多様化は多くの源からやってくる。言語が失敗したとき、以前の原理や再設 計に後退することで問題を解決しようという試みがあったのかもしれない; そ の方言が解決に失敗した問題への解決に適して見える異なるパラダイムを持つ 別の言語があるかもしれないし、おそらくその言語の印は抵抗できないほど魅 力的だろう; あるいは、純粋な知的または科学的好奇心が、新しい言語機能や パラダイムになる道に設計者を導くだろう。 1.2.4 受粉 言語設計と進化は、その経歴が、ある関心の集合から別の集合へ彼らを運ぶ ような人々によって駆動される。そして、薄い雪の層の上を転がる雪玉のよう に、人々は、働いている問題から影響を拾い上げる。だから、特定の個人たち が、Lispの多様化の物語に入ったり出たりすること、そして不在の後に再び現 れたときに、彼らは新たな経験を所有し、それらの経験を適用するだろうとい うことを観察する。新たなプレーヤーが現れ、他の人々と相互作用し、相互作 用の結果 - 言語 - が、多様な他の言語、言語の概念や機能、そして言語パラ ダイムへの知的な相性を反映するだろう。 受容グループは人間の集まりであり、言語の進化や多様化の全体の物語は、 人間の関心と制度の背景に反するものである。アピールは言語設計に対する客 観的な基準に対してなされるという事実にもかかわらず、避けがたい人間性が それを通して輝いている。 2 実装プロジェクト年代記 続く節は、1960年から現代までのLispの進化の中の出来事を記述する。それ ぞれの時代や状況は、純粋な年代記としてまず記述され、それから、時代や状 況の出来事が、多様化 - 受容 - 統合のサイクルのコンテキストの中に置かれ、 重要な技術的な概念が記述される。 結局Lispになった言語についての初めの考えは、John McCarthyが人工知能 のダートマス夏期研究プロジェクトに出席したときに始まった。実際の実装は 1958年の秋に始まった。1978年に、McCarthy は言語の初期の歴史[McCarthy, 1981]を述べたが、おおよそLisp 1.5の直後までを扱っている。[McCarthy, 1980]も参照のこと。Lisp 1.5から始まりMacLispやInterlispで終わるLispの 実装の短い記述から始める。そこでは、MacLispとInterlispをより深く探求し、 それらの開発と、それらが取り入れた異なる哲学を辿る。Scheme、Portable Standard Lisp、Zetalisp、そしてその他のCommon Lispの前身を含む、同時期 の他のLisp方言が次に示される。Common Lispは、その標準化と実装を含む詳 細について記述される。Lispへのオブジェクト指向テクニックのブレンドが、 特にCommon Lisp Object System (CLOS)への視点で考察される。ヨーロッパや 日本のLispの進化も考察されるが、Common Lispに反対して定義されたLisp方 言であるEuLispを除いてはあまり詳細にではない。 2.1 Lisp 1.5からPDP-6 Lispまで: 1960-1965 この時期、Lispは、別のコンピュータ上の既存のLispからのブートストラッ ピング、あるいは新たな実装のどちらかによって、種々のコンピュータへ急速 に広がった。ほとんど全ての場合、Lisp方言は小さく単純だった; 実装はまっ すぐだった。元の言語に対してなされた変更は極めてわずかだった。 1960年代初め、Timothy HartとThomas Evansは、Univac 490の軍用バージョ ンであるUnivac M 460上でLisp 1.5を実装した。それは、クロスコンパイラと、 Lisp実装の最も低いレベルのための少量の機械語コードを使って、IBM 7090上 のLisp 1.5からブートストラップされた[Hart, 1985]。 Robert SaundersとSystem Development Corporationの彼の同僚は、IBM製の AN/FSQ-32/Vコンピュータ - Q-32上でLisp 1.5を実装した[Saunders, 1985b]。 その実装はスタンフォード大学のIBM 7090とPDP-1コンピュータからブートス トラップされた。 スタンフォードでのPDP-1 Lispは、John McCarthyとSteve Russellによって 実装された。 1963年、L. Peter Deutsch(当時は高校生だった) は、Bolt Beranek and Newman (BBN)のPDP-1上にLisp 1.5に似たLispを実装した[Deutsch, 1985]。こ のLispはBasic PDP-1 Lispと呼ばれた。 1964年までに、Lisp 1.5の別バージョンが、Compatible Time Sharing System (CTSS)を走らせているMITの電気工学部のIBM 7094コンピュータ上で走っ ていた[?]。このLispとBasic PDP-1 Lisp は、1964年の春にDECとMITのテック 鉄道模型クラブの何人かのメンバーによって実装されたPDP-6 Lisp [PDP-6 Lisp, 1967]に大きな影響を与えた。このLispはPDP-6上で書かれた最初のプロ グラムだった。またこのLispは、MITのPDP-6や後にPDP-10上のIncompatible Time Sharing System (ITS) [Eastlake, 1968; Eastlake, 1972]の元で走るよ うに書かれたLispであるMacLispの祖先でもある。 BBNでは、Basic PDP-1 Lisp の後継がPDP-1上に実装され、MIT CTSSシステ ム上のLisp 1.5以降を手本とした上位互換バージョンが、Daniel Bobrow と D. L. Murphyによってscientific Data Systems 940 (SDS 940)上に実装され た。それ以上の上位互換のバージョンが、Alice HartleyとMurphyによって PDP-10に対して書かれ、このLispはBBN Lisp [Teitelman, 1971]と呼ばれた。 1973年、SDSがXeroxによって買収されてXerox Data Systemsと名前が変わって からそれほど経っていない頃、BBN Lisp の保守はBBNとXerox Palo Alto Research Centerに分担され、Lispの名前はInterlisp [Teitelman, 1974]に変 更された。 PDP-6 [DEC, 1964]とPDP-10 [DEC, 1969]コンピュータは、計画的に特に Lispに適するようになっており、36ビットのワードと18ビットのアドレスを持っ ていた。これは、CONSセル - ポインタまたはアドレスのペア - が単一のワー ドの中に効率よく格納されることを許した。CONSのCARやCDRの整形をとても速 くする、半ワードの命令があった。PDP-6とPDP-10は、速くパワフルなスタッ ク命令も持っており、Lispが速く関数を呼び出すことを可能とした。 これらの実装のほとんど全ては、小さな手でコード化された(アセンブリの) コアとコンパイラを持っていた; Lispの残りはLispで書かれ、コンパイルされ た。 1965年には、存在する全てのLispは事実上同じ、または些細な点で異なるだ けだった。1965年以降 - より正確にはMacLispとBBN Lispがお互いから分岐し た後 - 多数のLisp方言が現れた。 分析 これらの初期のLisp方言は、多様化ステージの典型的なパターンに当てはま る: これらの期間、言語の仕事に対する予算はあまりなく、グループは互いに孤 立しており、各グループは、少数の研究者に限られている局所的な受容グルー プのニーズを満たす方向に主に向けられていた。典型的な状況は、"廊下の先 に、LispウィザードがいるAIラボがある"という記述によって特徴づけられる。 この期間、実装戦略を伴うかなりの量の実験があった。統合の考えはあまりな く、特に正式な標準化プロセスの形成の考えはなかったが、それは、ある程度 は各研究所が具体化したパイオニアの感覚によるものだった。 最初の真の標準LispはMacLispとInterlispであり、それら自身が注目を受け るに値するものである。 2.2 MacLisp MacLispは、1960年代末から1980年代初めまで、MIT AIラボでの主要なLisp 方言だった。この期間のラボでの他の重要なLispの仕事は、Lisp-Machine Lisp(後にZetalispと名付けられた)やSchemeを含んでいた。MacLispは、通常 はPDP-10コンピュータと一体に考えられているが、他のマシン、Honeywell 6180のMultics operating system [Organick, 1972]の元でも動作した。 2.2.1 初期のMacLisp MacLisp/Interlisp時代のはっきり区別できる特徴は、製品品質もしくはそ れに近い品質の実装への注目である。この期間は、非常に詳細にまで注意を払っ た実装テクニックの統合を見た。 たとえば、Lisp 1.5では、スペシャル変数は識別子から場所への束縛であり、 それへのポインタは、その名前が識別子であるシンボルの属性リストに置かれ る。プログラマがxをスペシャルだと宣言するとき、コンパイラとローダが協 力してxという名前のシンボルを作る。xに対する属性リストは、スペシャルを 示す属性を持ち、その値はセルである。そのセルは、xが参照し、xへの代入が 値を置く場所である。xがletで束縛されたとき(名前xが新たに束縛されたとき)、 このセルにストアされている古い値は、制御がLET束縛地点を超えて戻るとき に古い値をこのセルへ戻すための十分な情報とともに、制御スタック上に置か れる。 common変数は、値セルがその値を保持するために使われるものであり、 common変数の束縛は、明示的な連想リストの使用を必要とする。実行時に common変数を評価するには、EVALへの呼び出しが必要である。 スペシャル変数は、異なるコンパイルされた関数間で共有できるが、インタ プリトされる関数では共有できない; common変数はコンパイルされた関数とイ ンタプリトされる関数によって共有され得るが、スペシャル変数と比べてずっ と遅い。 実装の点からは、スペシャル変数は現在浅い束縛として知られているものの 前身であり、一方、common変数は深い束縛の前身である。 浅い束縛の中では、スペシャル変数の値は、シンボルの値セルの中に常に保 持される。let 束縛では、シンボルは、古い値が制御スタック上に置かれるよ うに、そして新しい値がその値セルに置かれるようにする。LETの動的スコー プ内のシンボルの値への参照は新しい値を見るだろう。制御がLETを出るとき、 古い値が戻される。 深い束縛の中では、let束縛が生じるとき、識別子-値のペアは制御スタック 上に置かれる。シンボルの値への参照は、まずスタックでそこにある束縛を探 し、みつからない場合、値セルが参照される。スタックの探索は、スペシャル 束縛のブロック(識別子-値のペアがスタック上で格納される場所)を互いにつ なげることによって、シンボルが束縛されているかどうか(したがってスタッ ク上を検索すべきかどうか)を示すタグをシンボル中に置くことによって、あ るいは頻繁に参照されるだろうスタックフレーム中のスペシャル変数をキャッ シュすることによって、比較的効率的になし得る。これらのテクニックは、一 つだけで、あるいは組み合わせて使える。 初期のMIT PDP-6 Lisp [PDP-6 Lisp, 1967]の中で、Richard Greenblattは、 Lisp 1.5でのようにcommonとスペシャルの変数をどちらも持つことはエレガン トでないと決心した; 彼は言語からCOMMON変数を取り除いたが、スペシャル変 数が値セルを使って動作するようにした。これは、浅い束縛と呼ばれるものを 使った最初のLisp の実装だった。 MacLispとInterlispの間のキーとなる違いは、文法へのアプローチだった。 MacLispは純粋なリストスタイルを好み、トップレベルとしてEVALを使った。 Interlispは、Lisp 1.5と一緒に、EVALQUOTEを使った。MacLispでアトムaとb のドットペアを作るために、EVALへこの式をタイプするだろう: (cons (quote a) (quote b)) あるいは、(quote x)に対する文法的短縮である'xを使って、 (cons 'a 'b) Lisp 1.5では、EVALQUOTEへこのような式(実際は2つの式)をタイプできた: cons(a b) 名前EVALQUOTEの中の"quote"は、適用される関数へ"暗黙に引数を引用する" ことを表わす。MacLispは分岐し、トップレベルインターフェイスとしてEVAL だけを用いた。一方、BBNLisp(や、したがってInterlispも)は両方を収容し、 入力が1つのフォームの場合はEVALを、入力行が2つ以上のフォームの場合は APPLYを使った。 フレーズ"引数を引用する"は、実際には誤解のもとであり不正確である。そ れは、cons(a b)のようなフォームからの入力を(cons 'a 'b) のようなフォー ムへ変形する仮のプリプロセッサの動作を参照する。したがって、語 EVALQUOTEは、元のモデルの間違った理解を通じて生じた。類似の誤解が、い わゆるFEXPRまたは"特殊形式"の記述に持ち込まれた。Lispに関するいくつか の文の中で、実際に特殊形式がその意味を決定するための特別な規則を持ち、 その規則がいくつかのフォームを評価しないことを含むとき、"その引数を引 用する"特殊形式について話す特殊形式の記述を見つけるだろう[Pitman, 1980]。 McCarthy [McCarthy, 1981]は、元のLispインタプリタは万能チューリング マシンとみなされたと特に言及した: 命令の集合(関数)とテープ上の最初の入 力(引数)を与えられると、全ての計算を行なうことができた。したがって、 cons(a b)は(cons (quote a) (quote b))の変形版としてではなく、関数と(そ れとは別の)リテラルの引数リストとしてみなされることを意図したのである。 後から考えると、EVALQUOTEトップレベルはAPPLYトップレベルと呼ばれて、 EVALトップレベルと心地よく対称にした方が良かったかもしれないとわかる; BBN-Lispの文書はこの対称を明示的に書いていた。実際、以下の2 つの違い以 外は、EVALQUOTEはLisp 1.5の関数APPLYと同一だっただろう: (a) Lisp 1.5で は、APPLYは第3引数である環境を取った(今日では、ラムダ算法の忠実な反映 に対して必要とされる、レキシカルスコーピングではなく動的束縛の中で結果 として生じたなんらかの誤りとみなされている); そして(b) "EVALQUOTEは特 殊形式を一種の例外として扱える" [McCarthy, 1962]。今日では、このような 例外はクルージとして言及される[Raymond, 1991] (MacLispのAPPLYはこのク ルージをサポートしたことに注意)。 特殊形式は、関数やその上で呼び出すための引数の列を作るために、全ての 副式を評価するというデフォルトの規則によってではなく、特別の規則によっ てその意味が決定されるLisp 式である。たとえば、式(+ a b)の意味もしくは 操作は、aとbを評価し、その結果へ関数+ を適用することで決定される。式 (if a b c)の意味もしくは操作は、式aを評価し、その値が非NILの場合には式 bがifの値として評価され、NIL の場合には式cがその値として評価される。こ の意味で、ifは特殊形式と呼ばれる。 実際は、ifに関する語特殊形式は、ifは実際には特殊形式として取られるフォ ームと区別するために使われるオペレータの名前なので、誤解を招きやすい。 特殊オペレータとしてifを参照する人もいる。 これは、Lispコミュニティで何度か見るだろう傾向の一例 - 用語の誤用ま たは混乱した使用 - である。 Lisp 1.5 とMacLispでは、特殊形式は、印字名が特殊形式の名前に対応する シンボルの属性リスト上に関数を置くことで実装されている。たとえば MacLisp では、CONDはFSUBR属性を持つが、そこでFSUBR の中の"f"は特殊形式 を表わし、"subr"はコンパイルされたサブルーチンを表わす。引数に対する評 価プロセスは、プログラマの責任として残されている。以下は、MacLispの中 でどのようにIFが特殊形式として定義し得たかである(FEXPRはFSUBRのインタ プリトされるバージョンである): (defun IF fexpr (form) (let ((predicate (car form)) (then (cadr form)) (else (caddr form))) (cond ((eval predicate) (eval then)) (t (eval else))))) このコードは、でき得る限り効率的というわけではないが、特殊形式はユー ザによって書かれたコードで拡張し得ることを例証している。 MacLispはLEXPRを導入したが、それは任意個の引数を取ってスタック上に置 く関数の一種である; その関数の1つのパラメータは、渡された引数の数に束 縛される。この引数に対するラムダリストの形式 - シンボルでありリストで はない - がLEXPRの場合を通知する。以下は、引数のリストを戻す可変個の引 数の関数であるListをどのように定義するかの一例である: (defun LIST n (do ((i n (1- i)) (answer () (cons (arg i) answer))) ((zerop i) answer))) パラメータnは渡された引数の数に束縛される。式(arg i)は、渡された引数 のi番目を参照する。 LEXPR(とそのコンパイルされた対応物であるLSUBR)に対する必要は、+のよ うな可変項関数を持ちたいという欲求から生じた。n項の+に対する意味的な必 要性はないが、プログラマが、同等だがもっとかさばる(+ a (+ b (+ c d))) よりも、(+ a b c d)と書けることは便利である。後で、LEXPR の記法が、多 様化の間に新たな言語機能を実装するために有益であるような場所を、少なく とも他に1つは見るだろう。 DEFMACROがそれに基づいている、単純だがパワフルなマクロ機能は1960年代 中頃にMacLispに導入された。3.3節を参照のこと。 Lisp 1.5に対する他の主要な改善は配列; MEMBERのような単純な述語が有益 な値を戻すような関数であるように変更したこと; PROG2; そして、関数ERRを 導入してユーザコードがエラーを通知できるようにしたことである。 Lisp 1.5 では、ある種の組み込み関数が、たとえば不正な引数を与えられ たときに、エラーを通知してもよかった。エラーの通知は、プログラムの終了 かデバッガの呼び出しを通常引き起こした。Lisp 1.5は関数ERRSETも持ってお り、エラーを引き起こすかもしれないコードの制御された実行のために有益だっ た。特殊形式 (errset form) は、エラーがプログラムを終了したりデバッガに入ったりしないようなコンテ キストでformを評価する。formがエラーを引き起こさない場合、ERRSETは値の 1つのリストを戻す。formの実行がエラーを引き起こす場合、ERRSETフォーム は静かにNILを戻す。 MacLispは、エラーを通知する関数ERRを加えた。ERRがERRSETフォームの動 的なコンテキストの中で呼び出される場合、ERRへの引数がERRSETフォームの 値として戻される。 すぐにプログラマは、エラーの捕捉と通知のためではなく、もっと一般的な 制御の目的(動的な非局所脱出)のためにERRSETとERRを使い始めた。不幸なこ とに、このERRSETの使用は予期しないエラーも静かに捕捉し、プログラムのデ バッグを難しくした。ERRSETがもともと意図した使い方であるエラー捕捉のた めに取っておくことができるように、新たなプリミティブのペアであるCATCH とTHROWが、1972年6月にMacLispに導入された。 分析 ERRSETとCATCHの教訓は重要である。ERRSETとERRの設計者は、特定の状況を 思い浮かべ、その状況を扱うプリミティブのペアを定義した。しかし、これら のプリミティブの構造は2つの部分に分かれる: エラーを捕捉や無視する1つ目 の部分と、動的に前の地点へ制御を移す他の部分である。そのような非局所制 御移動プリミティブはなかったので、プログラマは意図しない方法で既存の機 構を使い始めた。それから、設計者は戻って望ましい機能に分割した。(注意 深い、あるいはそうではない)設計のパターン、意図しない使用、そして後の 再設計は普通のことである。 MacLispは大きなアセンブリ言語のコア、インタプリタ、そしてコンパイラ として書かれた。MacLispの開発者は、他の言語からのアイディアのいくつか を、典型的には合理化によって統合するとともに、新たなデータ構造で多様化 したことを、上で我々は見た。 MacLisp開発の次の段階は、MacLispの開発者が、大きくて影響力のある受容 グループ - プロジェクトMACやMathlab/Macsymaグループ - が現れることに気 づき始めたときに開始した。重点は、言語設計と実装自体を行なうことから、 それらのユーザコミュニティのニーズを満たすことへ変わった。 2.2.2 後期のMacLisp そのライフサイクルの後半生の間、MacLispは他のLisp方言や他の言語から の言語機能を採用し、いくつかの新たな物事が発明された。 MacLispに対する最も重要な開発は、1970年代始め、"高速算術コンパイラ "LISCOM [Golden, 1970]の中のテクニックがMacLispコンパイラに組み入れら れたときに起こった。この新たなコンパイラ、NCOMPLR [Moon, April 1974; White, 1969-1982; Pitman, 1983]は、他の全てのLispコンパイラが実行コー ドの速度に関して測定されたことに対して1つの標準になっただろう。MIT人工 知能研究所(AIラボ) の、視覚やロボット工学の分野でなされた算術計算をカ バーするニーズに触発されて、算術コードを表現あるいはコンパイルするいく つかの新たな方法が、コンパイルされたMacLispの算術処理性能をFORTRANコン パイラとほとんど同じくらいにした[Fateman, 1973]。 LISCOMは大部分Jeff Goldenの仕事だった。PDP-10上のコンパイルされた算 術LispコードとFORTRAN 算術コードの相対性能は、Digital社のコンパイラ作 者を奮起させ、Lispコンパイラが競争するのが難しいところまでDEC FORTRAN コンパイラを改善させた。算術コードに関するその後のLispコンパイラの相対 性能は、1972年に達した最高水位票に達することはなかったが、いくつかの Lispコンパイラはたいへんうまく行なった。 Bignum - 任意精度の整数算術 - は、Macsymaユーザのニーズに応えるため に1970年か1971年に加えられた。そのコードは、[Knuth, 1969] の中のアルゴ リズムの大体忠実な書き換えだった。後にBill Gosperがいくつかの改良、特 に整数bignum除算を速くするために、Lehmerの方法を用いる2進最大公約数ア ルゴリズムの良い機能を組み合わせた最大公約数の1バージョンを提案した [Knuth, 1981, ex. 4.5.2-34]。 1973年と1974年、David MoonがMultics下のHoneywell 6180上へのMacLispの 実装の努力を先導した。このプロジェクトの一部として、彼はMacLispに対す る最初の真に包括的なリファレンスマニュアルを書き、それは後に"Moonual" として俗に知られることになった[Moon, April 1974]。Richard Greenblattは、 1974年にMIT Lisp Machineプロジェクトを始めた; David Moon, Richard Stallman, そして多くの他のMIT AI LabのLispハッカーがやがてこのプロジェ クトに加わった。プロジェクトが進むにつれて、2つのプロジェクトが交差し て豊かになるように、言語機能が選択的にPDP-10のMacLispへ追加導入された。 複雑なラムダリストは、部分的にはMITのDynamic Modeling Groupのための 言語だったMDL [Galley, 1975]からの影響によって生じた。それは、AIや Mathlabマシンと同じマシン室に置かれていたPDP-10上で走った。Lisp 1.5の 質素な文法は、関数への引数の異なる役割を明快に表現するのに十分にパワフ ルではなかった。複雑なラムダリストは、この問題への解決法として現れ、広 く受け入れられるようになった; 結局それらは、その他の点ではエレガントな Common Lisp Object Systemを恐ろしく複雑にした。 MDL - その初めの、資金提供者の口にあまり合わない名前は"Muddle"だった - は、Lisp関連の言語であり、やはりMITで開発され、主流のLispの進化に強 い影響を与えた。それは、随意引数を表わす"OPTIONAL"、補助変数を定義する ための"AUX"、&rest変数(残りの引数のリストへ束縛される変数)のための "ARGS"、そして主流のLispの方言には入らなかったいくつか他のものをラムダ リストのオプションに導入した。MDLは、(Cの意味で)"左辺値"として記述され るかもしれないものであるlocativeを持っており、それだけがファーストクラ スだった; 本質的には、それらはメモリ位置へのポインタであり、それらの位 置を読み書きするための変数のように扱われ得る(C++では、この概念は参照と して知られている)。MDLは、値の列(セグメントと呼ばれる)が引数として広が るようにする連結マーカを持っていた; Common Lispのバッククォート文法の 中で使われる連結マーカ,@はこれから来た。またMDLは、末尾にPを使った主流 のLisp方言とは対照的に、述語を暗示する名前の最後に?を使うことを例を通 じて導入した(Schemeは現在"道理にかなった"?の慣習を、Common Lispは"伝統 的な"Pの慣習を使っているので、数にだけ真である述語はScheme ではNUMBER? と、Common LispではNUMBERPと呼ばれる)。 Lisp-Machine Lisp はラムダリストとlocativeを拾いあげ、評価とバッククォ ートの中の連結マーカを適合させたが、その概念の進化は、見かけと効果にお いてLisp-Machine Lispとたいへんよく似ている形式に洗練されたが実際の実 装は極めて異なっていたConniver [?]に受け継がれる。Schemeは、述語に対す る末尾の"?"の使用を拾いあげた。MDLは、Lisp-Machine Lisp, Conniver, そ してCommon Lispのさまざまな実装の中にさまざまな形式で再度現れたマルチ タスク機能を持っていた。 MacLisp はリードテーブルの記法を導入した。リードテーブルは、プログラ ムとデータに対してプログラム可能な入力文法を提供する。文字が入力される とき、テーブルは、トークンにまとめるのに使うために、その文字の文法的な 特質を決定するために調べられる。たとえば、テーブルは、どの文字が空白を 表わすかを決めるために使われる。さらに、関数は文字に関連づけられ得るの で、ある文字が読まれたときにはいつでもある関数が呼び出される; 呼ばれて いるデータ構造の中に組み入れられるように値を戻す前に、関数はさらに入力 を読むことができる。このように、組み込みのパーサはユーザによってプログ ラムし得る。このパワフルな機構は、(quote x)に対する'xのような単純な短 縮から、逆引用符機構や入念なAlgolスタイルのパーサにまで及ぶ、Lisp に対 する代替入力文法の実験を容易にした。これらの実験にいくつかのついてのこ れ以上の議論は3.7.1節を参照のこと。 リードテーブル機構を用いて、たとえばCGOL [Pratt, 1976]のような、 MacLispに対するいくつかの異なる表面上の文法が使われた。 今なお続いているLispの問題は、その文法が、ある人々に対しては不慣れで 禁じられているので、採用することを人々が躊躇することである。多くのプロ グラマはAlgolのような文法を好む。1991年、CAD Framework Initiativeグル ープ(??? 参照先は最近のScheme Digestメッセージ) は、その拡張言語として Schemeを使うことを票決したが、Cのような表面上の文法を使いたいと表明し た。同様に、1989 Common Prototyping Language研究グループ[?]は、多くの Lispの機能と、しかしありふれた表面上の文法を持つ言語を使うことを推奨し た。 1971年、Jon L White (原文のまま)は、名前(文字列)をシンボルへマップす るデータ構造の表現をリストからハッシュ表へ変更した[White, 1969-1982]; したがって、伝統的なLisp 1.5のOBLIST(オブジェクトのリスト、すなわち名 前を持つアトム)はOBARRAYと改名された。これは、サイズやスピードを最適化 するために、もっと注意深くデータ構造を選ぶようになる先駆けとなった。後 のLispの実装は、実装の部分に対して、ハッシュ表にもっと大きく依存するよ うになった。OBARRAYの導入は、Lisp実装の洗練の増加の中の1つの重要なステッ プを刻印した。 Jon L Whiteは一般に"Jonl"として知られており、それは"O'Donnell"のよう に"jonnell"として、あるいは"john-ell" のどちらかのように発音され得る。 このため、彼の名前は正しい"John L. White"ではなく、通常"Jon L White"と 書かれる。 MacLisp入出力システムへの大きな改善が1974 年に実装された。その時点よ り前は、1つのMacLispプログラムは、同時に1つの入力ファイルと1つの出力ファ イルと、キーボードと端末画面への別の接続だけしか持てなかった。いわゆる NEWIOシステムの下では、オープンされるファイルの数はオペレーティングシ ステムによってだけ制限された(ITSは16 という上限まで差し支えなかったが、 それは当時は非常に大きな数と考えられた!)。NEWIOファイルの下、というよ りはオープンされたファイル接続は、引数として渡され、値として戻され、そ して ゴミ集めされるファーストクラスのオブジェクトになった(実装の最もト リッキーな部分の1つは、ファイルオブジェクトが回収されたときにファイル が清潔にクローズされることを確実にすることだった)。 Unixが普及する前、プログラミング言語の設計の中と同じくらい、オペレー ティングシステムの設計の中で多くの実験があった。ちょうどそれぞれの研究 所が自身のLisp方言を持っているかもしれないのと同様に、それぞれの研究所 が異なるオペレーティングシステム - 完全に自家製ではない場合なら、どこ かよそから入手したものの局所変異 - を走らせていることは稀ではなかった。 1978年には、別の団体と、MacLispで書かれたMITソフトウェアを共有したいと いう欲求があった。多くの主要な研究所は同様にPDP-10を、2台ではないとし ても1台は持っていたが、いずれもITSが走っていたのではなかった。したがっ て、MacLispは5 つの別のPDP-10オペレーティングシステムへ移植されなけれ ばならなかった: - TOPS-10, PDP-10に対するDEC自身のオペレーティングシステムで、その中で ユーザとファイルディレクトリは、483,11823のように、10進数で表現され る2つの18ビット整数で識別された - CMU TOPS-10, 整数のペアではなく、N920JW51のような記憶を助ける識別子 によってユーザとファイルディレクトリを識別するためにカーネギーメロン 大学で局所的に修正された(この例では、JWはJon Whiteを表わし、5はアカ ウントが1978年に割り当てられたことを、1は彼はイニシャルJWを持つその 年の2番目のユーザだったことを意味する - 2つの文字と2つの数字は18ビッ トの中にエンコードできることに注意) - WAITS [?], スタンフォードでの、もっとずっと広範囲に変異したTOPS-10の 別バージョンであり、それぞれ3文字までの2つの語(Lisp文書に対して LSP,DOC、Richard P. Gabrielに対して1,RPGのように - 3つの6ビット文字 (小文字はない)は18ビットに入ることに注意!)によってユーザとファイルディ レクトリを識別した - TENEX, BBNで開発され、TOPS-10とは完全に異なり、31文字までのユーザ、 ディレクトリ、そしてファイル名を用いた - TOPS-20, DECがTENEXを取り入れて飾り立てた結果 この移植の努力は簡単だったが退屈で、MacLispのマスターのアセンブリ言語 ソースファイルへ、大部分は入出力ルーチンの中に、何百もの条件アセンブリ コマンドを挿入することを必要とした。 分析 MacLispは、1960年代初頭のLisp実装の疾風の統合として見られ得る。Lisp 1.5の派生の安定した、高い処理性能を持つ実装への統合を駆動した特定の受 容グループ - プロジェクトMAC - があった。したがって、サイクルの最初の 例を見ることができる: Lisp 1.5 の時代の間の多様化、MITのプロジェクト MAC時代の初めの受容、プロジェクトMACの全盛期の間の統合、そして、後で見 るように、多様化の時期に先立つMIT でのLispに対する資金の縮小である。 1969年から1981年までの期間、MacLisp はいくつかの受容グループに恵まれ た: 1969年から1973年頃まで、それはAIラボ、とりわけ視覚グループだった。 1972 年から1981年頃まで、それはMathlab/Macsymaグループだったが、 William Martinの下での初期Mathlabグループは強い影響があった。 AIラボは人工知能一般の研究を指揮したが、視覚、ロボット工学、自然言語、 プランニング、そして表現に焦点を合わせた。さらに、Carl Hewitt, Terry Winograd, Gerry Sussman, そしてGuy Steeleによって例証されるように、AI のための言語の設計にいくらか関心があった。 MathlabとMacsymaグループは記号数学に興味があり、それが数学の構造と概 念を記号的に整形するためのアルゴリズム、データ構造、そしてプログラムを 開発する訓練だった。たとえば、記号的微分(数値的微分とは対照的)は、最初 の記号数学プログラムの1つである。 ?1972年から1983年まで???、MacLispに対するサポートは、Macsymaコンソー シアムやいくつかの新たな開発に対するエネルギー省の資金を持つMacsyma グ ループによって提供された。Macsymaコンソーシアムは、たとえばLawrence Livermore 国立研究所のように???、仕事のためにMacsymaを使っている団体の グループであった。一般に、これらのメンバーもエネルギー省によって資金を 供給されていた。 このように、MacLispは受容グループを持っており、グループはその標準と してMacLispを受容した。それでも、MacLispはPDP-10の上でだけ走ったので、 他の言語との統合を通じて言語を標準化する必要はほとんどなかった。しかし、 MacLispは、他のLisp方言から少数の機能だけを採用した。1974 年、約1ダー スの人々がMITでのMacLispとInterlispの実装者間のミーティングに出席した が、そこにはWarren Teitelman, Alice Hartley, Jon L White, Jeff Golden, そしてGuy Steeleが含まれていた。実際の共通基盤を見つける望みがいくらか あったのだが、そのミーティングは、実際には、実装の詳細から全体の設計哲 学までの全てにおいて、2つのグループを分離する大きな意見の隔たりを例証 するのに役立った(それぞれの側が選んだ戦略から離れたがらなかった理由の 多くは、1メガ、1 MIPSのマシンであるPDP-10上で既知であった厳しい資源の 制約におそらく由来する。もっと速いスピードともっと大きなアドレス空間を 持つMIT Lispマシンの出現で、一度はプログラミングツールを分離した小さく パワフルな実行環境を擁護した人々は、Lisp中にプログラミングツールを書き、 Lisp環境を完全なプログラミング環境へ変える戦略を取り入れた)。結局、些 細の機能の交換だけが"偉大なMacLisp/Interlispサミット"からの結果だった: MacLispは(CAR NIL) -> NILと(CDR NIL) -> NILの振る舞いをInterlispから採 用し、Interlisp はリードテーブルの概念を採用した。 NIL のInterlispの扱いの採用は、皆に温かく受け止められたのではなかっ た。Jon L Whiteによる公式発表を引用する[White, 1969-1982, July 9, 1974, item 2]: Interlispとの互換性のために(あーあ)、NILのCARとCDRは常に、本当に常に NILである。NILはなお属性リストを持ち、GETとPUTPROPはなお動作するが、 NILの属性リストはそのCDRではない(きわどい、きわどい)。その要求は、以下 のようなコードを (CADDR X) (AND (CDR X) (CDDR X) (CADDR X)) もっと時間や空間を消費するものなどの代わりに書けるようにするというもの である。不平はGLSへ送ってほしいが、それがあなたのためになるかどうかは わからない。 2、3の説明の言葉が必要である。問題の源の一部は、MacLispでは、アトミッ クなシンボルへ適用されるCDRはそのシンボルの属性リストを戻したというこ とである。この変更によって、シンボルNILは、その属性リストを得る方法が ない点で他の全てのシンボルとは違うようになる。CDRがシンボル上でこのよ うに動作するようになったのは、ユーザが大いに依存し始めた実装のアクシデ ントだった - これは、ERRSETとERRで見た、意図しない機能の使用の別の一例 である。それで、CDRに対する契約は一様ではなかった: ドットペアへ適用さ れたときは1つのことを行ない、そしてシンボルへ適用されたときは、同じマ シン命令によってたまたま実装された、抽象的には無関係なことを行なった。 解決法は、属性リストに対する抽象操作の集合を完全にすることだった; PLISTとSETPLISTが1975年、Interlispとの互換性変更の約9ヶ月後にMacLispへ 導入されたので、CDRとRPLACDがシンボルに使われる必要はない。 ユーザが参照できるMacLispについての情報源があった: 1. オリジナルのPDP-6 Lispマニュアル[PDP-6 Lisp, 1967]とその更新版[?]。 2. LISP ARCHIV [White, 1969-1982], 言語の新たに加えられたり削除された りした機能それぞれをリストする完全なオンラインログ。MacLispのそれぞ れの新リリース毎に、リリースノートがログの前の方に追加された。この ファイルは1969年から1981年まで、Jon L WhiteがXeroxのためにMITを離れ るまで保守された(奇妙なスペリングはITSの設計の結果であり、ITSはファ イル名をそれぞれ最大6文字までの2つのコンポーネントに限っていた。 TOPS-10では、その6と3の制限と異なる句読法で、そのファイルはLISP.ARC と呼ばれた)。 3. MacLisp Manualの1974年版[Moon, April 1974], Multics上にMacLispを載 せる努力の一部としてDavid A. Moonによって書かれた。この有用な文書は、 通常口頭では"Moonual"として参照された。 4. Jon L WhiteはMacLispの短い歴史を出版した[?]。 5. 1983年にKent Pitmanによって書かれたThe Revised MacLisp Manual。 6. "廊下の先のウィザード": 実装者であるMITのJon L WhiteやGuy Steele、 スタンフォード大学のRichard P. Gabriel、オーストラリアの???大学の Rodney A. Brooks、CMUのDavid Touretzky、イリノイ大学のTimothy Finin のような地元のMacLisp導師たち。Ray Bradburyの華氏451度の中の亡命者 たちのように、これらのおそらく熱狂的なハッカーが文書そのものであり、 リクエストすれば必要な情報を暗唱しただろう - おそらく今日の観点から は嘆かわしい状況だろうが、素早く変化するソフトウェアで仕事をする小 さなコミュニティの中では機能した。 7. ソースコード。MacLispコミュニティの精神の一部は、言語が行なうことに ついて何か疑問があるときは、コードを読むことができるというものだっ た。 MacLispは主にPDP-10上で走り、ソースコードファイルの単一で中心的な集合 があったので、相対的に小さくタイトなニットのようなコミュニティは、別の、 完全な言語仕様の必要性をあまり感じなかったことに注意しよう(MacLispが2 つのマシンアーキテクチャにまたがり始めたときに作られたMoonualはそのル ールを証明する例外である; しかし、PDP-10民族はMulticsコミュニティをア ウトサイダーとみなしたので、そのルールは、新たな変更はLISP ARCHIVの中 でアナウンスされるようにしておくことを歓迎し続けた。Moonualは、Kent Pitmanが"Pitmanual" [Pitman, 1983]として知られるようになるものを作るま で、9年間改訂されなかった)。 Interlispの努力は、対照的に、もっとずっと荒々しいユーザコミュニティ に対する包括的なリファレンスマニュアルと、Interlispを別のコンピュータ アーキテクチャへ移植することを助ける、別個の仮想マシン仕様を生み出した。 MacLispコミュニティがMIT Lisp Machineコミュニティに変身していき、もっ とよい文書が必要になり、再びDavid MoonとこのたびはDaniel Weinrebとによっ て、ついにそれが現れた[Weinreb, November 1978](これは、"chine nual" (sheenualと発音される)と呼ばれたが、それらの文字だけが表面に見えるよう に、大きなブロック体のタイトルLisp Machine Manualがペーパーバックカバ ー全体に覆われていたためである)。 いくつかの他のプログラミング言語がMacLispの中で開発された: 2、3の例 をあげるとMicro-Planner, Conniver, そしてSchemeなどがある。Extendや Flavorsを含む、MacLispへのいくつかのオブジェクト指向拡張が試みられた。 Extend [Burke, 1983]は、継承を使って組み込みのLisp型システムを拡張する ためのメカニズムであり、Flavorsは以下で詳細に議論されるだろう。1970年 代中頃までに、PDP-10のアドレス空間の制限 - 256k 36ビットワード、すなわ ち1メガバイト - がLispプログラムのサイズが大きくなるに従って厳しい制限 に成りつつあることがますます明らかになっていた。この時期までに、 MacLispは、いくぶん小さいがたいへん影響力のあるユーザコミュニティの中 で、ほぼ10年に及ぶ強力な使用と受容に恵まれていた。大きなアセンブリ言語 コアの実装戦略は、それが位置しているような方言でいるためには手に負えな いことがわかってきており、他の方言や他の言語からの知的圧力や、実装者た ちによる言語設計の熱望がLispに対する新たな方言になろうとしていた。 多くの人たちにとって、安定してMacLispを使っていた時期は、全てがLisp の世界に正しかった黄金期だった(この同じ時期は、今日ではノスタルジーに ふける多くの人々によって、人工知能の黄金期としてみなされてもいる)。 1980年までにMacLispに対する受容グループは衰えていた - Macsymaに対する 資金はあまり長くは続かないだろうと思われた。AIの中のさまざまな予算の危 機はAIラボのLispウィザードたちの地位を枯渇させ、MITとMITの取り巻きから のウィザードのコアグループは新たな団体に移った。1970年代終わりと1980年 代始めは多様化の期間だった。 すでに見たいくつかの名前が再び現れるだろう - White, Steele, Moon, Greenblatt, McCarthy, Deutsch, Bobrow, そしてGabriel - そして残りは消 えるだろう。 2.3 Interlisp Interlisp(とそれ以前はBBN-Lisp)は、Lispプログラミングスタイルと方法 論に多くの革新的なアイディアを導入した。これらのアイディアの最も目に見 えるものは、スペリング訂正器、ファイルパッケージ、DWIM、CLISP、構造エ ディタ、そしてMASTERSCOPEのようなプログラミングツールの中に具体化され た。 これらのアイディアの起源は、人間-コンピュータの共存に関するWarren Teitelmanの博士論文[Teitelman, 1966]の中に見出し得る。特に、("テキスト "や"テープ"編集[Rudloe, 1962]に対立するものとしての)構造編集、ブレーク ポイント、アドバイス、そしてCLISPの起源を含んでいる(William Hennemanは、 1964年に、Lispに対する英語あるいはAlgolのような表面上の文法(3.7.1節を 参照)であるA言語のための翻訳器について記述したが[Henneman, 1985]、それ は到底CLISPのように精巧または柔軟なものではなかった。Hennemanの仕事は Teitelmanに直接は影響しなかったように見える; 少なくとも、Hennemanの論 文を含んでいる同じコレクション[Berkeley, 1985]の中の他の論文を引用して いるが、それを引用していない)。 スペリング訂正器とDWIMは人間の弱点を補うように設計された。シンボルが 値(あるいは関数定義)を持っていないとき、Interlispのスペリング訂正器 [Teitelman, 1974]が呼び出されるが、それはシンボルが誤って綴られただろ うからだ。スペリング訂正器は、もしかしたら誤って綴られたシンボルを既知 の語のリストと比較した。ユーザは、スペリング訂正に関してシステムの振る 舞いを制御するためのオプションを持っていた。システムは3つのことのうち の1つを行なうだろう: (a) 自動的に訂正する; (b) 一時停止し、提案された 訂正が受け入れられるかどうかを尋ねる; あるいは(c) 単にエラーを通知する。 スペリング訂正器は、"私の意図したことをせよ(Do What I Mean)"の名をとっ てDWIMと呼ばれる、もっとずっと大きなプログラムの一般的な制御の下にあっ た。どんな種類のエラーでもInterlispシステムによって発見されたときはい つでも、DWIMが正しいアクションを決定するために呼び出された。DWIMは丸括 弧のエラーのいくつかの形式を訂正することができたが、それは、識別子のス ペルミスとともに、ユーザによる最も普通の誤植を構成した。 エラーの訂正が永続的になされないのなら、DWIMは特に有用ではなかっただ ろう(毎日毎日同じエラーを認識したい人がいるだろうか?)。Interlispは、関 数定義のファイルを、たとえばMacLispと同様に維持するのではなかった。 MacLispユーザにとっては、ASCII文字のファイルがプログラムの主要な表現だっ た; これらのファイルは、それから走っているシステムへ読み込まれるか、後 にロードされるためにバイナリコードへ事前コンパイルされるかだった。 Interlispでは、ファイルは、ユーザソースコードを格納するための、走って いるLispシステムに外部的な不揮発性の格納メディアとしても使われた; しか し、ユーザはファイルを直接調べることはほとんどなく、そのフォーマットに ついてもほとんど気にしなかった。ユーザコードへの全ての変更は、 Interlispプログラミング環境の中でなされた。InterlispユーザはASCIIエディ タを使ってファイルを修正するのではなく、プログラムのS式表現を編集する ために、専属のLisp構造エディタを代わりに使った。 Interlispが、ファイルを使って、近づいた理想的な状況は、ユーザはけっ して終了しないLispシステムと相互作用し、使うことが重要であってファイル の中のテキストとしての表現が重要ではないものがプログラムである、という ものだった。DWIMによってエラーが修正されるとき、メモリ中のプログラム表 現がその訂正を反映するように変更され、そして、ユーザの視点からはほとん ど付随的な副作用として、プログラム表現に対する不揮発性のバックアップメ ディアとして提供されるファイルも更新される。従って、一度バグが修正され れば、それは永久に修正された。 CLISP(対話型LISP, Conversational LISP)は、通常のInterlisp文法の中に 組み込まれた、Algol風と英語風文法を混ぜたものだった。以下は、Interlisp のCLISP文法で書かれた正しいFACTORIALの定義である: DEFINEQ((FACTORIAL (LAMBDA (N) (IF N=0 THEN 1 ELSE N*(FACTORIAL N-1))))) CLISPも、一般的なDWIMメカニズムに依存していた。それは、実際には、トー クンを再配列して括弧を挿入しなければならないだけでなく、N=0やN*のよう なアトムをいくつかの適切なトークンへ分割しなければならないことに注意し よう。従って、ユーザは前置オペレータの周りに空白を置く必要はない。 CLISPは繰り返し構文の便利な集合を定義した。以下は、m≦p≦nの範囲の全て の素数pを印字する単純なプログラムである: (FOR P FROM M TO N DO (PRINT P) WHILE (PRIMEP P)) CLISP, DWIM, そしてスペリング訂正器は、FACTORIALの正しい定義として以 下を認識するように一緒に動作できるだろう[Teitelman, 1973]: DEFINEQ((FACTORIAL (LAMBDA (N) (IFFN=0 THENN 1 ESLE N*8FACTTORIALNN-1)))) Interlispは、このボロボロの定義を前に示した正しいフォームへ最終的に"訂 正する"。shift-8は、ビットペア(bit-paired)のキーボードを持っていた、 Model 33テレタイプ上の左括弧であることに注意しよう。DWIMは、タイプライ ターペア(typewriter-paired)のキーボード(左括弧はshift-9であり、shift-8 はアスタリスクだった)が普通になったときに変えられなければならなかった。 (Interlispに批判的な人たち、とりわけMacLispの支持者だった人たちは、 DWIMはTeitelmanがしがちで、他の人はしない特有のタイプミスへ調整されて いるようだと、正当にあるいは不当に、しばしばコメントした。これらの批判 者たちは、DWIMを以下のような展開だとDWIMをしばしば風刺した: "Teitelman が意図することをせよ(Do What Teitelman Means)"あるいは"Interlispが意図 することをせよ(Do What Interlisp Means)" "システムに自動的にプログラム を'訂正'させますか? 私はそれをよく思わないのです!" MacLisp支持者は、 MacLispはDDWIDMを使うと答えただろう: "私が意図しないことをするな(Don't Do What I Didn't Mean)") Interlispは構造エディタを持っていた。Lispコードが表示され、Interlisp システムの中で変更された。エディタの中のオペレーションは、現在のS式 - ユーザによって選択されたとき - か、現在の式を取り囲む小さなコンテキス トへ適用された。このエディタは、テレタイプや他のものが遅く、印字端末が 標準だったときに開発された; Interlispの構造エディタは、そのような端末 上でプログラマがLispソースコードをたいへん効率的に編集することを可能に した。この編集のスタイルは、ほとんどもっぱらLispでだけプログラミングを 行なっている人々には自然だが、常にASCIIテキストを編集することを好む人々 もいる。 MASTERSCOPEは、大きなシステムの中で関数についての情報を見つけるため の機構だった。MASTERSCOPEは、コードの本体を分析し、データベースを構築 し、そして対話的に質問に答えることができた。MASTERSCOPEは、どの関数が どの他の関数を(直接あるいは間接に)呼ぶか、どの変数がどこで束縛されるか、 どの関数があるデータ構造を破壊的に変更するか、などの関係を追跡した (MacLispはINDEXと呼ばれる対応するユーティリティを持っていたが、同じく らい一般的あるいは柔軟では到底なく、バッチモードでのみ走って、完全な相 互にインデックスづけられたレポートを含むファイルを生成した)。 Interlispはブロックコンパイルの概念を導入したが、それは、その中では 複数の関数が単一のブロックとしてコンパイルされるというものである; これ は、そうでなければInterlispの中で可能だっただろうよりも速い関数呼び出 しを結果として生じた。 Interlispは、PDP-10、Vaxen(複数のVax[Raymond, 1991])、そしてXeroxや BBNで開発された種々の特殊目的のLispマシン上で動作した。最も普通に利用 可能なInterlispマシンは、Dolphin, Dorado, そしてDandelion(集合的にDマ シンとして知られている)だった。Doradoは3つのうちで最も速く、Dandelion が最も普通に使われた。異なるInterlisp実装が特殊変数を扱うために異なる テクニックを使ったことは興味深い: Interlisp-10(PDP-10用)は浅い束縛を使っ たが、Interlisp-D(Dマシン用)は深い束縛を使った。これらの2つの実装テク ニックは、異なる処理性能のプロフィール - 一方の体制の下である実行時間 のプログラムが他方の下では10倍長い時間がかかり得た - を示す。 この予期しない処理性能の状況はLispでは一般的である。実装を理解してい るときにのみ、プログラマはある言語の中で効率的なコードを生成すると主張 できる。Cでは、Cのオペレーションはvon Neumannアーキテクチャコンピュー タのマシンオペレーションと密接に対応しているので、実装はまっすぐである。 Lispでは、実装はまっすぐではないが、実装のテクニックや選択の複雑な集合 に依存する。プログラマは、選択されたテクニックだけでなく、それらのテク ニック使用時の処理性能効果にも精通している必要があるだろう。よいLispプ ログラマを見つけることがよいCプログラマよりも難しいのは不思議ではない。 ちょうどMacLispの入出力システムがITSによって提供される機構の周りに設 計されたように、Interlispの入出力システムはTENEXの機構の周りに設計され たが、それは、いろいろ考えてみると、ITS(割り込みハンドリングのような領 域ではもっと不様だったが)の機構よりも多くの点で進んだものであり、もっ と親しみのあるユーザインターフェイスを提供していた。Interlispのファイ ルは、どこでも名前によって表現された; 全ての入出力関数(readやwriteもそ うであり、単にopenやcloseだけではない)は、ファイルを名付ける文字列を受 け入れた。従って、同時に多くのファイルを開くことができたが、ファイルは、 自動回収に従うファーストクラスのLispオブジェクトによって表現されるので はなかった。 MacLispのように、Interlispは、どのように引数が関数へ渡され得るかに関 して、Lisp 1.5の関数呼び出しメカニズムを拡張した。Interlispの関数定義 は、2つの属性の交わった結果として引数を指定した: LAMBDA対NLAMBDA、そし てspread対nospreadである。LAMBDA関数は引数のそれぞれを評価する; NLAMBDA関数は引数のどれも評価しない(すなわち、呼び出しの評価されない引 数の部分フォームは引数として渡される)。spread関数は固定個数の引数を必 要とする; nospread関数は可変個数を受け入れる。これらの2つの属性は完全 に直交的ではない。なぜなら、nospread NLAMBDAのパラメータは評価されない 引数フォームのリストへ束縛されたが、nospread LAMBDAのパラメータは渡さ れた引数の数へ束縛され、ARG関数が実際の引数値を取り出すために使われた からである。InterlispとMacLispのメカニズムの間にはこのように緊密な対応 があった: Interlisp MacLisp LAMBDA spread EXPR LAMBDA nospread LEXPR NLAMBDA spread no equivalent NLAMBDA nospread FEXPR しかし、MacLispとInterlispの間には別の重要な違いがあった。MacLispで は、"固定個数の引数"は極めて厳格な意味を持っていた; 3つの引数を受け入 れる関数は、正確に3つの引数で呼び出されなければならず、多くても少なく てもだめだった。Interlispでは、全ての関数はあらゆる数の引数で正しく呼 び出されることができた; 余分な引数フォームは評価されてそれらの値は捨て られ、ない引数値はデフォルトでNILになった。これは、1974年のサミットで 双方を隔てていた、主な調停不能な相違の1つだった。それ以来、MacLispパル チザンは、統制がとれておらずエラーを起こしがちだとしてInterlispをあざ けり、一方Interlispファンは、MacLispは不器用で柔軟性がないと考えたが、 なぜなら彼らは、&optionalや他の複雑なラムダリスト文法が、ゲームの終わ り頃、Lisp-Machine Lispから追加導入されるまでMacLispには来なかった、付 加引数の便利さを持っていたからである。 Interlispによって導入された言語拡張の最も革新的なものの1つはスパゲッ ティスタック[Bobrow, 1973]だった。スペシャル変数が存在する動的関数定義 環境の(クロージャによる)保持の問題は、スパゲッティスタックが発明される までは完全に解決されることはなかった。 スパゲッティスタックの背後にあるアイディアは、その枝へのポインタが保 持されるときはいつでも保持に従うさまざまな枝を持つ木にもっと似るように、 スタックの構造を一般化することである。すなわち、スタックのいくつかの部 分は、他のLispオブジェクトと同様のゴミ集めポリシーに従う。クロージャと は異なり、保持される環境は、制御環境と束縛環境をどちらも捕らえる。 スパゲッティスタックは、本来、線形スタックを用いる木構造のスタックの 効率的な実装である; スタックのいくつかの部分が保持されないような状況で は、処理性能上のペナルティはほとんど負わない。 Interlispは、MacLispよりもずっと広い範囲でLisp 1.5の風味を保持してい た。MacLispは(MAPCARや他のMAP関数のような)いくつかの関数へのいくつかの 引数の順序を変えたが、Interlispはオリジナルの順序を保持した。Interlisp のプログラミングスタイルは、プログラミング環境、CLISP、そしてDWIMに強 く影響されている; したがって、InterlispのLisp部分は初期のLispへの類似 性を大いに残しており、プログラミングスタイル改良の努力はCLISPやDWIMに 集中している。MacLispのような方言では、その中に"Lisp的な"スタイルは保 持されていたが、言語自身のLisp部分が進歩した。 Interlispが行なったあまり重要ではない、しかし興味深い文法の拡張の1つ は、スーパー括弧、あるいはスーパー角括弧の導入だった。read操作中に右角 括弧]に出会う場合、全ての未解決の左括弧を、あるいは最後の未解決の左角 括弧[までを釣り合わせる。以下は、この文法の単純な例である: DEFINEQ((FACTORIAL (LAMBDA (N) (COND [(ZEROP N) 1] (T (TIMES N (FACTORIAL (SUB1 N] 分析 MacLispとInterlispは、同時期に存在するようになり、互いに同じくらい長 く続いた。それらは、受容グループが異なっていたが、2つのグループの一般 的な記述は両者を区別しなかった: どちらのグループも、主にARPA(後に DARPA)によって資金を提供されたAI研究所の研究者たちであり、それらの研究 者たちはMIT、CMU、あるいはスタンフォードで教育された。主な実装は同じマ シン上で走り、一方は快適な環境を持つLispとしての印を持ち、他方は引き締 まった、巧みな、ハイパワーのLispだった。主な違いは、プログラミングの問 題への異なる哲学上のアプローチから来ていた。ユーザグループからの異なる プレッシャーもあった; MacLispユーザ、特にMathlabグループは、よく最適化 されたコンパイラや、自身の使用のためにPDP-10アドレス空間の多くの部分を 使わずに残しておくことと引き替えに、あまり統合されていないプログラミン グ環境を使うことを望んだ。Interlispユーザは、完全な、統合された開発環 境を使うことで、コーディングの仕事に集中することを好んだ。 MacLispの哲学は、質の高い実装、処理性能、テキストエディタ、そして言 語の表現力に中心を置いた。Interlispの哲学は、プログラミング環境とコー ディングの仕事 - その頃はプログラミングの仕事と呼んだだろう - に中心を 置いた。MacLispはファイルに基づいた、テキストエディタ指向の環境であり、 一方Interlispはメモリ内(コア内)Lisp構造エディタを持つ常駐環境だった。 MacLisp環境は、互いに緩やかに結合される外部ツールを使い、一方Interlisp 環境は、言語実装と堅く結び付いていた - 実際、環境と言語は同じアドレス 空間を共有し、実際に同じプログラムの一部だった。 Interlispの哲学は、1960年代中頃に大部分はTeitelmanによって発展したが、 その頃には大きなスクリーン端末はほとんどなかった - 印刷テレタイプ型端 末がたいてい普通だった。そして、主なテキストエディタは"テープエディタ" だった。テープエディタは、テキストが長い線状のテープであるかのようにテ キスト上で動作するテキストエディタである。コマンドは、いくらかの距離あ るいは検索のどちらかによって、テープ上を前方や後方へ動いた。テキストは 挿入したり削除したりできた。当時人気があったエディタの1つであるTECOは、 もともとはテープエディタ兼コレクタ(Tape Editor and Corrector)(後にはテ キストエディタ兼コレクタ(Text Editor and Corrector))と呼ばれた。要する に、コード入力や修正のプロセスは、Interlisp環境の外ではたいへん難しかっ たので、Interlisp開発環境のゴールは、そのプロセスを単純化および短くす ることだった - コードをタイプすることすら難しかったので、ショートカッ トが探求された。 Teitelmanのアプローチは新しくわくわくするもので、確かにコーディング の生産性を改善した。 もう一方であるMacLispも、同様にある種の長所を持っていた。言語の実装 はファイルベースかつテキストベースだったので、開発環境は、独自の進化の プロセスに従い得る独立した外部ツールによって捕らえられ、MacLispプログ ラマたちはその利点を実際に受けた。しかし、Emacs[?]が現れるまでは、あま り利点は持たなかった。 ツールが分離されたとき、ユーザは、言語同伴のツールの集合を受け入れる 必要はない。選ぶべきパッケージと、環境のツールが不適当な危険がある場合、 言語と環境を選ぶコストは、ある人々にとっては高過ぎるかもしれない。 しかし、MacLispプログラマは生産性を改善してほしかった - 実際は、彼ら はおそらく生産性については気にせず、仕事を単純に、そしてもっと楽しくし たいだけだった。その結果、MacLisp開発者たちは言語自身にもっと集中し、 マクロと新たなデータ型を追加し、処理性能を改善した。 他の哲学の違いの集合はプリティプリンティングにある。以下は関数の定義 の一例であり、Lisp 1.5の中のMEMBERである。Lisp 1.5 Programmer's Manual [McCarthy, 1962]の中に現れるものを正確に再現した: DEFINE(( (MEMBER (LAMBDA (A X) (COND ((NULL X) F) ((EQ A (CAR X) ) T) (T (MEMBER A (CDR X))) ))) )) 今日のCommon Lispで書かれた同じプログラムは、このようになるだろう: (defun member (element list) (cond ((null list) ()) ((eq element (first list)) t) (t (member element (rest list))))) 最新のインデントは、コードの意味のある部分の関係を明らかにするように 設計されている。古いスタイルは、なんの設計もないように見える。 この中間の例は、1966年のコーディングスタイルに由来する: DEFINE(( (MEMBER (LAMBDA (A X) (COND ((NULL X) F) ((EQ A (CAR X) ) T) (T (MEMBER A (CDR X))) ))) )) このスタイルの設計は、関数名、引数、そしてCONDのまさに最初をイディオム とみなしているように見え、それゆえそれらは同じ行に一緒にある。COND節の ブランチが一列にならんでおり、それが場合の構造が考慮されていることを示 している。 MacLispでは、インデントのスタイルは意識的に進化したが、それは、少な くともEmacs [?]のようなテキストエディタが半自動的なインデント機構を加 えるまでは、プログラマ自身がインデントを行なう責任があったからである。 プログラムコードは、テキストエディタによって、あるいはプリントアウト上 で見られたのに対して、Interlispでは、プログラムコードは、それだけとい うわけではないが、主にスクリーン上で見られた。 Interlispは、メモリ中のプログラムをとり、ファイルまたは端末へそれを ダンプするプリティプリンタを提供した。構造エディタは、プログラムコード を表示するためにプリティプリンタを使った。そのプリティプリンタは未熟に プログラム可能だったが(???)、それをカスタマイズする人はほとんどいなかっ た。(フォントは???)。MacLispはプリティプリンタを持ち、プログラマは自身 のプリティプリントスタイルを採用していたので、プリティプリンタはプログ ラム可能でなければならず、事実そうなっていた[White, 1969-1982; Moon, April 1974; Pitman, 1983; ?; Steele, 1990c]。 もちろん、Interlisp開発者たちはInterlispを改良したが、主な言語の改善 はスパゲッティスタック(や、ゆえに一種のダイナミッククロージャ)、レコー ドパッケージ、そしてフィールドに基づいた構造体だった。処理性能に関して は、Interlisp開発者たちはブロックコンパイルと、1つ以上のPDP-10アドレス 空間の使用を加えた。 しかし、言語拡張のための主なメカニズムは、環境を通してのものだった。 DWIM、スペル修正器、そしてCLISPは、表面の文法を変え、ある種のエラーの タイプを大目に見ることで、新たな言語を定義することに役立った。 その結果、Interlispでは言語の実験よりも環境の実験が多く行なわれ、一 方その逆がMacLispでは真であった。これらの2つの方言は、1970年代を通って 1980年代まで、1980年代初めの大きな統合が行なわれるときまでの主要な方言 であり、MacLispとその派生物は断然最も強い影響を与えた。これは、 Interlisp内のコアLisp言語の停滞のためである。この停滞は、Interlisp開発 者たちによる環境への関心の代償だった。 もちろん、Interlispの逝去には別の要因があり、Interlispは、まさに最後 まで素晴らしい健康と新たな前途に恵まれているというチャンピオンとしての 信念が、逝去の少なからぬ要因だった。 Interlispも、多様化と受容の後の統合を示し、その後の多様化の活動は環 境に集中しており、コア言語にではなかった。MacLispとは異なり、Interlisp の開発者たちは、他のマシンへ移植することを通してInterlispを広めようと したが、MacLisp開発者たち - それぞれは新たな組織で新たな言語のアイディ アを試した - は、新たな設計と新たなLispの変形を作ることで多様化した。 2.4 1970年代初期 MacLispとInterlispは1970年代を支配したが、この期間に使われたいくつか他 の主要なLisp方言があった。多くは、InterlispによりもMacLispに似ていた。 2つの最も広く使われた方言は、Standard Lisp [?][Marti, 1979]とPortable Standard Lisp [Group, 1982]だった。Standard Lispは、Anthony Hearnと Martin Grissによって、彼らの生徒や同僚たちと一緒に1966年[Griss, 1982] に定義された。その動機は、Lispプログラム、とりわけ記号代数システム REDUCEを移植するための媒体として役にたち得る、Lisp 1.5や他のLisp方言の 部分集合を定義することだった。 Standard Lispは、存在するLispの実装("ターゲットのLisp(target Lisp)" と呼ばれた)がStandard Lisp構造を実装できる場合、Standard LispとREDUCE がその既存の方言の上で走ることができるように設計された。 後にHearnと彼の同僚は、よい処理性能のためには環境やコンパイラ上にもっ と制御が必要だということを発見し、Portable Standard Lisp (PSL)が生まれ た。Standard Lispは既存のLispの背に乗ろうと試み、一方PSLは、Lispコンパ イル技術の進化の中での重要な先駆的努力であるretargetableコンパイラ [Griss, 1981]を用いる完全な、新たなLispの実装だった。1970年代末までに、 PSLは12以上の異なるタイプのコンピュータ上で動作した。 PSLは2つのテクニックを使って実装された。第1に、生の、型のない表現上 でオペレーションをコードするために使われた、SYSLISPと呼ばれるシステム 実装言語を使った。第2に、c-macrosと呼ばれる、パラメータ化されたアセン ブリレベル翻訳マクロの集合を使った。Portable Lisp Compiler (PLC)は、 Lispコードを抽象アセンブリ言語へコンパイルした。この言語は、コンテキス トの中でc-macro記述を抽象命令にパターンマッチングすることで、マシン依 存のLAP(Lispアセンブリプログラム(Lisp Assembly Program))フォーマットへ 変換された。たとえば、異なるマシン命令が、オペランドのソースやオペレー ションの結果のデスティネーションによって選ばれるかもしれない。 1970年代後半から1980年代中頃まで、PSL環境は、エディタや他のツールに 適合することで改善された。特に、Emodeと呼ばれた、立派なマルチウィンド ウのEmacs似のエディタが、かなりインテリジェントな編集や、Lispとエディ タの間で前後に情報を渡すことを可能にするように開発された。後に、Nmode と呼ばれた、もっと広範なEmodeの版が、カリフォルニアのパロアルトにある Hewlett-Packardで、Martin Grissと彼の同僚たちによって開発された。この PSLとNmodeの版は、1980年代中頃にHPによって商品化された。 1960年代にスタンフォードで、MacLispの初期の版がPDP-6へ適合させられた; このLispはLisp 1.6 [Quam, 1972]と呼ばれた。その初期の適合はJohn Allen とLynn Quamによって書きなおされた; 後にコンパイラの改良がWhit Diffieに よってなされた。 UCI Lisp [Bobrow, 1972]は、Interlispスタイルのエディタやその他のプロ グラミング環境改善がなされたLisp 1.6の拡張版だった。UCI Lispは、他の組 織でと同様に、1970年代の初めから中頃までの間、スタンフォードで何人かの 人々によって使われた。 1976年に、MacLispのMIT版がスタンフォード人工知能研究所(Stanford AI Laboratory, SAIL)のRichard Gabrielによって、WAITSオペレーティングシス テムへ移植されたが、それはその頃John McCarthyによって指揮されていた。 この方言は、UCI Lispを含むLisp 1.6の派生を押しのけた。Edward Feigenbaumの指揮下にあった発見的プログラミングプロジェクト(Heuristic Programming Project)では、Interlispが第一の方言だった。Cordell Greenの 自動プログラミンググループ(PSI)は、南カリフォルニアのInformation Science Institute (ISI)にあるPDP-10へのリモートログイン経由でInterlisp を使っていた。 Analysis Standard LispとPSLは、さまざまなLisp方言を使うある範囲のユーザへ、特定 のプログラムReduceを配達することを主な焦点とした、アイディアの統合を示 していた。Reduceのユーザは増えており、それを使うことを熱望していた。こ れらの2つの方言は、有益なReduceシステムの普及のために必要なものとみな されていた。Standard Lispは既存のLispの背に乗ろうとする試みであり、一 方PSLはもう少しうまく処理性能を制御しようとする試みを示していた。 UCI Lispは、単純なLisp 1.6ベースへのInterlispの適合であるので、これ をInterlispの統合の一部とみなし得る。 Lisp 1.6自身は1970年代中頃に姿を消し、Lisp 1.5時代の最後の遺物のひと つとなった。 2.5 PDP-10の逝去 1970年代の中頃までには、PDP-10の18ビットのアドレス空間は、AIプログラム に対する十分な作業空間を提供しないことが明らかになっていた。PDP-10コン ピュータの系列(KL-10やDEC-20)は、拡張されたアドレッシング機構を許すよ うに変更され、その中では複数の18ビットのアドレス空間が、30ビットのベー スレジスタ相対のインデキシングによってアドレスされることができた。 しかし、この追加は、Lisp実装者が考える限りでは、アーキテクチャへのス ムーズな拡張ではなかった; 1語に2つのポインタから1語に1つのポインタだけ への変更は、ほとんど全ての内部データ構造の完全な再設計を必要とした。拡 張アドレッシングに対しては2つのLispだけが実装された: Rutgers [?]の Charles HedrickによるELISPと、PSLである。 アドレス空間問題に対する1つの反応は、特殊目的のLispマシンを作ること だった(2.6節を参照)。他の反応は、もっと大きなアドレス空間を持つ商用コ ンピュータを使うことだった; これらの最初のものはVAX [DEC, 1981]だった。 Vaxは、Lisp実装者たちへ好機と問題の両方を提供した。Vaxの命令セットは、 低レベルのLispプリミティブを効率よく実装するための、いくつかのよい機会 を提供したが、それは賢い - おそらくあまりに賢い - データ構造の設計を必 要とした。しかし、Lispの関数呼び出しは、VAXの関数呼び出し命令を用いて 正確にモデル化されることはできなかった。さらに、VAXは、その理論的には 大きなアドレス空間にもかかわらず、明らかに多くの小さなプログラムによる 使用のために設計されており、いくつかの大きなプログラムのためにではなかっ た。ページテーブルはメモリのあまりに大きな部分を占め、大きなLispプログ ラムに対するページングのオーバーヘッドは、VAX上で完全に解決されること が決してなかった問題だった。最後に、先行投資の問題があった; 当時の1つ 以上の主要なLisp実装は、移植することが難しい大きなアセンブリ言語のベー スを持っていた。 最後の打撃は、DECがVAXに集中するために全PDP-10アーキテクチャを捨てた ときに来た。振り返ってみると、これは、DECの方では確かによい戦略的判断 だったが、当時は、PDP-10を愛しているLisp実装者たちに、VAXに憤慨する別 の理由を与えただけだった。ラッキーな何人かは、自身のハードウェアを設計 や製作するための資源を持っていた; 残りの人々にとっては、VAXは町での唯 一のゲームだった。PDP-10の熱狂的ファンにとって、それは遅く、高価で、愛 されそうにないものに見えた。 1970年代後半に開発された主なVaxのLisp方言は、VAX Interlisp、PSL(VAX へ移植された)、Franz Lisp、そしてNILだった。 Franz Lisp [Foderaro, 1982]は、MITでのMacsymaの主要な実装者の1人であっ たRichard J. Fatemanの監督のもと、カリフォルニア大学バークレイ校で記号 代数の研究を継続できるように書かれた。Fatemanと彼の学生は、ハーバード 大学で書かれたPDP-11版のLispから始め、Franz Lispがほとんど完全にCで書 かれていた事実のおかげでやがては事実上全てのUnixベースのコンピュータ上 で動作するMacLisp似のLispへ拡張した。後にFranz, Inc.,が、Franz Lispを 促進するために作られた; Franz Lispの開発と販売は今日まで続いている。 Franzは、主に記号代数の研究のための媒体として意図されたので、MacLisp がそうだったような意味において堅固なLispになることはなかった。他方、そ れは、AIコミュニティで最も広く利用可能なコンピュータの1つで広く利用可 能なLisp方言だった。 MacLispの後継として意図されたNIL [Burke, 1983]は、MITで開発された Lisp-Machine Lispの影響のもと、Jon L White、Guy L. Steele Jr.、そして 他のMITの人々によって設計された。その名前は、"Lispの新たな実装(New Implementation of Lisp)"に対するあまりにうまい頭字語であり、ある程度の 量の混乱を引き起こした。NILは大きなLispであり、効率への関心は、MacLisp 起源の実装者たちの心の中で最高の位置を占めていた; まもなく、その実装は 大きなVAXアセンブリ言語ベースに集中した。 1978年に、GabrielとGuy Steeleは、Lawrence Livermore国立研究所 [Correll, 1979; Hailpern, 1979]によって設計と作成がなされていたスーパ ーコンピュータS-1 Mark IIA上にNIL [Brooks, 1982a]を実装し始めた。この Lispが完全に機能したことはなかったが、Lisp実装へ先進的なコンパイラテク ニックを適合させるためのテストベッドとして役にたった。特に、その仕事は MacLispコンパイラの数値計算テクニックを一般化し、それらを主流のレジス タ割り当て戦略[Brooks, 1982b]と統一した。S-1 Lispコンパイラの開発を用 いて、LispでLispを実装し、最もよく手で調整された、アセンブリ言語ベース のLispシステムと同様の処理性能を期待することが再度実行可能になった。 1975年に、Gerald J. SussmanとGuy L. Steele Jr.は、アクタ計算モデルの 結果を理解しようとする試みの中で、いくつかのインタプリタを用いた実験を 始めた(この実験は、2.8節で説明されている)。これは、Schemeと呼ばれる新 たなLisp方言を記述した一連の論文の、1976年から1978年の間の発表になった。 Schemeは、レキシカルスコーピング(その対照のローカルスコーピングは、 ほぼ10年間Lispコンパイラで使われていた)とファーストクラスの関数の意味 を真剣にとらえた最初の言語の1つである。すなわち、Schemeはクロージャを 正しく扱った - クロージャは、定義されたときのローカルな環境をその中に 一緒に持つ関数である。さらに、関数呼び出しは、戻るだろう手続きへのcall としてではなく、手続きへのjumpとして扱われ得るという意味において、アク タ計算モデルを取り入れた。 その理論は、計算の残りは、継続と呼ばれる別の関数(あるいはSchemeの用 語では手続き(procedure))の中にカプセル化されると述べた。継続は1つの引 数をとり、それは渡される(戻される)値である。これは、継続渡しと呼ばれる プログラミングのスタイルをもたらす。たとえば、xとyを掛けた結果に7を加 え、継続contへその結果を与えることはこのように書かれるだろう: (* x y (lambda (temp) (+ temp 7 cont))) したがって、各プリミティブ関数はその継続である追加の引数をとり、だから 約束により、それはユーザ定義の関数でもよい。 インタプリタの設定では、この引数は暗黙でありうる。明示的なときは、* の定義はこのようになるだろう: (define * (lambda (m1 m2 cont) (cont (*$ m1 m2)))) ここで、*$は低レベルの乗法プリミティブである。 Schemeは、3つの影響力の強いScheme論文に基づいたインタプリタ、コンパ イラ、そしてシステムを書いた、理論好きでエレガンスと単純さに興味がある 人々の崇拝者をゆっくり集めた。他のLisp開発者たちは、言語の明快さとその 体裁に魅せられ、彼らの受容グループが必要としたそれほどきれいではない言 語よりもSchemeに対する好みを、何年にもわたって宣言したものだった。 1970年代の終わりには、Schemeは、少なくとも1つのよいコンパイラを持っ ていた[Steele, 1978a]。 1970年代中頃のフランスでは、Greussay [Greussay, 1977]がVlispと呼ばれ るインタプリタベースのLispを開発した。Interlispのベース方言のレベルで は、別の評価器の実体を作ることによって、割り込みや、traceやstepのよう な環境的関数を実装するための一種の動的環境であるchronologyのような、い くつかの興味深い概念を導入した。Vlispの重点は、速いインタプリタを持つ ことにあった。そのコンセプトは、評価器を輸送するために使われる仮想マシ ンを提供することだった。この仮想マシンはアセンブリ言語のレベルにあり、 容易な移植と効率的な実行のために設計された。そのインタプリタは、2つの 事柄から、そのスピードのかなりの部分を得た: 異なる項数のかなりの関数を 識別する関数型空間を用いる速い関数ディスパッチと、末尾再帰除去である (Vlispは、一般的な末尾再帰除去をサポートする、おそらく最初の製品品質の Lispだった。MacLispを含むその頃の他の方言は、ある条件のときだけ、予測 が保証されないようなやりかたで、末尾再帰除去を行なった。)。Vlispは、 1980年代の間、フランスやヨーロッパで重要なLisp方言の1つであったLe Lisp の前身だった; その2つの方言は同じではなかったが、いくつかの実装テクニッ クを共有した。 分析 PDP-10は、初期のLisp方言がその上で極めてうまく実装されるように設計され ていた: メモリアドレスが18ビットでワードが36ビットだったので、CONSセル は1ワードにぴったり入り、ハーフワードを扱う便利な命令があり、そして関 数呼び出しメカニズムはLispに従順だった。 Vaxの出現でこれは変わった。Lispデータ構造とVaxアーキテクチャ機構の間 に簡単な対応関係はなかった。さらに、好まれるVax手続き呼び出し命令は、 新たなMacLisp似のLisp方言のスタイルにうまくフィットしなかった: これら の各方言は可変個の引数をサポートし、そしてVax命令セットは、Lispのため に実行可能な関数呼び出しをつぎはぎして作り上げるいくつかの方法はあった が、固定個の引数を用いる関数呼び出しだけをサポートした。しかし、Cや FORTRANのような別の言語が、お互いに話をするために学ばれることが、Lisp がみんなの仲間になるのにさらにもう1つの障害になった。 1970年代の終わり、Lispに適した新たな商用マシンはなくなりかけていた; Vaxがそこにある全てのように見えた。Glenn Burkeによる何年にもわたるすぐ れたサポートにもかかわらず、Vax NILは広く受容されるには至らなかった。 Interlisp/VAXは処理性能上で大失敗だった。"汎用"ワークステーション(すな わち、Lisp以外の言語を実行するように意図あるいは設計されたもの)やパー ソナルコンピュータは、まだ完全には現れてはいなかった。多くのLisp実装者 やユーザにとって、商用ハードウェアの状況は極めてわびしく見えた。 しかし1974年から、Lispマシンに対する研究とプロトタイピングプロジェク トがあり、1970年代の終わりには、Lispマシンは未来の波のように見えた。 この点で、MacLispに対する自然な受容グループは衰退し、しかしInterlisp の受容グループが優勢になる状況を持つ; これらのグループは、合併されよう としている、営利に関心があるAIグループである。Interlispは、営利受容グ ループによって受け入れられるマシンの集合で動作し、彼らの仕事のスタイル に合っている。Interlispのための新たなLispマシン(別の節で議論される)は、 はっきりした印を持つ。おそらく、MacLispユーザを引き入れてすら、 Interlispが統合の権利を主張するのに機は熟している。 MacLispは、さまざまなLisp-Machine方言による多様化の段階に入っている。 Lispマシンは、容易に受容され得るにはあまりに新しいように見える; そして、 それらの新たな開発環境は、受容段階へ移行するには、古いスタイルの MacLisp開発からおそらくあまりに多くの変更がある。しかし、それらは確か に印を持っている。 そのレースは、Lispが成功することを助けるために、誰が正しい特徴を持つ マシンを選び得るかを知ることになるだろう。目下の問いは、Vaxが正しいマ シンになるのか、Lispマシンなのか(そしてその中のどれなのか)、あるいは、 そのときは知られていないマシンになるのかである。そのときには知られてい ないマシンになることがわかるだろう。 Franz LispとPSLは、互換性を除いて新たな受容グループを提供することは 何もしていないことや、Lispとしてのそれぞれは、もっと以前のMacLisp時代 への先祖返りであることに注意しよう。移植性は、重要な生き残りのための特 徴のようだが、なんらかの印なしでは、方言に望みはほとんどない。 Schemeは、我々のサイクルのテーマの興味深い変種に相当する。Gerry Sussmanは、いろいろな言語グループと関係した: MDL(またはMuddle)グループ、 Micro-Plannerグループ、そしてConniverグループである。Schemeの後、彼は 制約言語上で働こうとした。彼のターゲットの聴衆は、Sussmanの仕事に関係 する仕事に加わっている研究者、あるいはSussmanの言語の1つを使うことを望 む研究者を加えた彼自身である。 Sussmanの仕事は常に印を持っている - Micro-PlannerからConniverを通っ てSchemeまで - そして彼の仕事はほとんど常に受容を得るが、その受容グル ープは強い態度を取らないので、これらのアイディアは常に流行るわけではな い。 驚くべきはMDLの例外である: Sussmanはこのグループに属したが、MDL自身 は流行らず、MITではそれはあまり高くみなされなかった。それにもかかわら ず、MDLからの非常に多くのアイディアがConniverと、後にLisp-Machine Lisp で流行った。Common Lispと、ある程度EuLispで、これらのアイディアがしっ かりと現役であることを見る。それなのに、これらの言語を使う人々のどれだ け多くがMDLを、あるいはその主な設計者Chris Reevesを知っているだろうか? したがって、Sussmanは1970年代の間、小さな受容の聴衆がいるとするなら ば、受容/統合段階が極めて短い多様化発生人だった。 全体的なコンテキストでは、Schemeは、他の方言の統合段階の間に使われる 概念を提供できた。1980年代のSchemeを見るとき、何か他の可能性と一緒に、 Schemeに対する1つの主要な受容グループが見えるだろう。Schemeに対する主 要な受容グループは、Scheme報告書の種々の改訂版の著者たちの集合である。 2.6 Lispマシン Lispについての議論は、その上でLispが動作できるハードウェアのタイプに従っ て2つのカテゴリーに分けられ得る。2つの重要なカテゴリーは、普通のハード ウェアとLispマシンである。普通のハードウェアマシンとは、汎用コンピュー ティングのために商業的に設計されたものである。我々の議論の目的のために は、普通のハードウェアコンピュータは、Lispをサポートするために特に設計 されたのではないコンピュータとしてとらえることができる。たとえば、 Digital Equipment Corporation Vax 11/780は普通のハードウェアであり、 Symbolics 3600はLispをサポートするためにとくに設計されたコンピュータの 一例である。何人かのLispマシン設計者は、普通のハードウェアコンピュータ をFORTRANマシンと呼ぶ。 我々は用語"普通のハードウェア"を、今日の他の人々が用語"汎用コンピュ ータ"を使うかもしれないような場所で使う。"特殊用途ハードウェア"と対照 になるので、後の用語が少しだけもっと適切にも思える。しかし正しい対照は、 普通の能力を持つ汎用ハードウェアと、追加の能力を持つ汎用ハードウェアの 間にある。Lispプログラムを実行している間に頻繁に行なわれるオペレーショ ンのいくつかは、特殊なハードウェアによって、もっとうまく処理されるか、 あるいはかなり速度を向上し得る(Lispマシン上の特殊なハードウェアによっ て行なわれる、最も頻繁にハードウェアの助けを借りるオペレーションは、タ グ付け、関数呼び出し、そしてゴミ集めである)。しかし、Lispマシンは一般 に、少なくとも原理的には、FortranあるいはCのコードを実行するためにも使 える汎用コンピュータである。 Lispマシンの記憶域のワードは、ポインタを直接サポートするのに十分なビッ トを持つように設計され得る - アドレスとタグビットは、アドレッシングビッ トを全く失うことなく、記憶域のワードにどちらもフィットできる。ポインタ のタグをチェックする命令は、コンピュータの特殊なデータパスを用いて速く することができる。加算のようなオペレーションは、オペレーション自身と並 行にオペランドの型をチェックでき、型が適切ではない場合、例外条件がタグ 付けされ、もっと一般的なアクションのコースがそれからとられ得る。 関数呼び出しは、Lispプログラムの中で最も頻度の高いオペレーションの1 つである。スタックフレームの構築はハードウェアによってなされ得る。スタッ クのキャッシュ部分は、Lisp実装に対する主要な処理性能の相違になり得る。 ゴミ集めは、必要に応じてしばしば行なわれる - 動的なヒープが自由空間を 使い尽くしたとき、ゴミ集めが、いくらかの自由空間を獲得するために開始さ れ得る。ゴミ集めは比較的長時間かかることがあり、他のLispオペレーション と並列に行なえば、ゴミ集めに関する長い休止を除去できる。インクリメンタ ルなゴミ集めのために知られているテクニックの多くは、特殊なハードウェア を用いて最もよく実装される。 多くのLispマシンは本質的に、Lispに対して特別にマイクロコード化された 汎用コンピュータである。 Lispマシンに対するアイディアは、以前から非公式に議論されていたが、 Peter Deutschが最初の具体的な提案[Deutsch, 1973]を発表したようである。 Deutschは、Lispを走らせるために特別にマイクロコード化され、Lisp開発環 境をサポートする、一人のユーザ用のミニコンピュータクラスのマシンの基本 的なビジョンを概説した。Deutschの論文からの、Lispに永続的なインパクト をもたらした2つのキーになるアイディアは、(1)関数に基づいたロードとスト アのアクセスの二重性と、(2)CDRコーディングを通じた線形リストのコンパク トな表現である。 そのときまでの全てのLisp方言は、ドットペアの1番目のコンポーネントを 読むための1つの関数CARと、その同じコンポーネントに書くための、名目上は 無関係な関数RPLACAを持っていた。Deutschは、CARのような関数は"ロード"モ ードと"ストア"モードをともに持つべきだと提案した。(f a1 ... an)がロー ドモードで呼び出される場合、値を戻すべきである; (f a1 ... an v)のよう にストアモードで呼び出される場合、新たな値vが、ロードバージョンによっ てアクセスされるだろう場所に格納されるべきである。Deutschは、各アクセ サ関数に関係する2つの内部関数、1つはロードに対するもの、もう1つはスト アに対するものがあるべきであり、ストア関数は、特定の特殊形式の集合の中 で言及されたときに呼び出されるべきであると指摘した。しかし、彼の文法は 示唆に富んでいる; 以下は提案されたRPLACAの定義である: (lambda (x y) (setfq (car x) y)) Deutschは、"関数を引用して、その他全てを評価する"ので、ここで使われる 特殊形式はSETFQと呼ばれるとコメントした。この名前は、Lisp-Machine Lisp でSETFと短縮された。Deutschは、二元的な関数のアイディアはAlan Kayの作 だとした。 2.6.1 MIT Lisp Machines: 1974-1978 Richard Greenblattは、1974年にMIT Lisp Machineプロジェクトを始めた; 彼 の提案[Greenblatt, 1974]は、Deutschの論文を引用している。そのプロジェ クトは、Thomas Knight, Jack Holloway, そしてPitts Jarvisを含んでいた。 彼らが設計したマシンはCONSと呼ばれ、その設計は、Xerox PARC ALTOマイク ロプロセッサ、DEC PDP-11/40、CMUによってなされたPDP-11/40の拡張、そし てDECのSam Fullerによって提案された命令変更に関するいくつかのアイディ アに基づいていた。 このマシンは、よい処理性能を得るために設計されたと同時に、MacLispに 上位互換だが、"Muddle-Conniver"引数宣言文法を加えたバージョンのLispを サポートしていた。その他のゴールは、法外ではないコスト(1台70000ドル以 下)、単一ユーザ操作、手続き呼び出しの標準化を伴う共通のターゲット言語、 コンパイルされたプログラムに対してPDP-10よりも3倍よい記憶域の効率、型 チェックとゴミ集めに対するハードウェアサポート、大部分はLispでコード化 された実装(アセンブリ言語や低レベルの実装言語への少ない依存)、ディスプ レイ指向の相互作用、長い稼働時間(マシンのリブートとLispの開始の必要が 稀であること)、以下に記述されるさまざまなテクニックを用いるフレーム指 向の記憶域である。 CONSマシンは、PDP-10の間接ポインタの一般化である見えないポインタをサ ポートするためのものだった。間接ポインタは、以下の効果を持つメモリ記憶 域フォーマットだった: Mが、位置Tへの間接ポインタを含むメモリ位置である 場合、Mからフェッチする特別な命令は、Tからは見えずにフェッチし、Mへス トアする特別な命令はTへストアする。通常のメモリ命令は、MへストアしてM からフェッチするだろう。 見えないポインタは、命令からデータへ、そのような間接指定を切り替える ことでこのメカニズムとは異なり、たとえば位置Mの特殊なタグは、特殊な命 令ではなくTへの間接参照が使われることを通知するだろう。 見えないポインタは、以下の事柄のために使われた: - ガーベジコレクタのオペレーションが、Lispシステムのオペレーションに 点在するようなインクリメンタルなゴミ集め。コピーコレクタでは、オブ ジェクトがコピーされるとき、古い位置への参照が新たな位置へ転送され るように、転送ポインタ、すなわち見えないポインタは残される。 - 純粋なCONSセル表現ではなく、線形の、ベクタのような表現がリストに対 して使われるCDRコーディング。この表現では、ベクタの各要素はCARに論 理的に格納されるオブジェクトを含み、その要素は次に連続するセルは CDRであることを示すようにタグ付けられる。RPLACDがそのようなリスト 上で使われるとき、古いベクタ要素は、より最適化された表現の代わりに 真のCONSセルを指す見えないポインタで置き換えられる。従って、CDRコ ーディングの記憶域の節約は最大限に保持され得る。 - スペシャル変数と局所変数の統一した扱い。スペシャル変数は、値セルへ の見えないポインタを用いて位置として表現され得るので、同じアドレッ シングモードがスペシャル変数と局所変数を参照するのに使える。 - オブジェクトが実際のコンポーネントへの見えないポインタであるような ところで、参照のために使われるオブジェクトがある場合、MDLで定義さ れるものと類似のlocativeが実装され得る。 CONSマシンは作られた; それから、CADRと名付けられたその次の改良版が設 計され、何ダースかが作られた。CADRは、特にLispに有用ないくつかのデータ パスを用いる、特別にマイクロコード化された、32ビットのプロセッサだった。 これらは、MIT AI Labでの計算の大黒柱になり、このマシンを商業化するため の会社を独立して作ることは賢明に思われた。しかし、主だった人たちの間の 意見の相違のために、2つの会社が作られた: Lisp Machines Incorporated (LMI)とSymbolicsである。当初は、それぞれがCADRのクローンを製造した。そ の後まもなく、Symbolicsは3600系列を導入し、その後5年の間、それはLispマ シンの処理性能の業界リーダーになった。 一方Greenblattは、速いゴミ集めをサポートするためのハードウェアメカニ ズムを提供することに特に注意を払ったが、実際初期のMIT Lisp Machineは、 何年ものかなり長い間ガーベジコレクタを実装しなかった; いやむしろ、ガー ベジコレクタが現れたときですら、ユーザは無効にすることを好んだ。多くの プログラミングツール(とりわけ、コンパイラとプログラムテキストエディタ) は、可能ならばいつでも、コンスすることを避け、一時的なデータ構造を明示 的に回収するように設計された; こうなっていれば、ユーザが、ディスクへ動 作中の"世界"を保存して再起動しなければならなくなるまで、数日あるいは数 週間でさえ動作できるほど、Lisp Machineのアドレス空間は十分大きく、仮想 メモリシステムは十分よくできていた。そのようにディスクへあちこちをコピ ーすることは、遅く、手動で起動されるコピーガーベジコレクタと同等だった (1970年代に、さしはさみ(interleaved)ゴミ集めや並行(concurrent)ゴミ集め に関する非常に多くの理論的な研究があったが[?; ?; Baker, 1978; ?]、連続 的(continuous)ゴミ集めは、David Moonが即時(ephemeral)ゴミ集めを発明し てLisp Machine上に実装するまで広く受け入れられることはなかった[Moon, 1984]。即時ゴミ集めは、普通のハードウェアで使われるようにその後に改造 された)。 初期のMIT Lisp-Machine Lisp方言[Weinreb, November 1978]は、MacLispに とてもよく似ていた。それは、最少の移植の努力だけでMacLispプログラムを サポートするという、その明言されたゴールに応えた。MacLispを越える最も 重要な拡張は以下を含んでいた: - 主に常駐のコンパイラ、デバッグ機能、そしてテキストエディタから構成 される、改善されたプログラミング環境。これはLisp-Machine Lispに、 Interlispの完全にLispベースのプログラミング環境の理想への接近をも たらしたが、それはまだ確固としてファイル指向だった。テキストエディ タはEMACSクローンであり、最初はEINE(EINEはEMACSではない(EINE Is Not EMACS))と呼ばれ、後にZWEI(ZWEIは最初はEINEだった(ZWEI Was EINE Initially))と呼ばれたが、もちろんドイツ語のバージョン番号として二 重に面白い再帰頭字語である。 - &optional, &key, &rest, そして&auxを含む、複雑なラムダリスト - 構造の真ん中を指すCのような能力を提供するlocative - ずっと便利なマクロ定義機構であるDEFMACRO。これは、マクロ関数へ渡さ れるフォームの部分を参照するためのメカニズムを提供するマクロ定義機 構である。3.3節を参照。 - テンプレートを埋めることでデータ構造を構築するための文法であるバッ ククォート。これはリストを構築するための機能であり、MDLの評価モデ ルやConniverのリスト構築機構に由来する。 - コルーチン機構を提供したスタックグループ - リストを構築することなく、関数呼び出しから1つより多い値を戻す能力 である多値。これ以前は、さまざまなアドホックなテクニックが使われて いた; Lisp-Machine Lispは、そのためのプリミティブを提供した最初の Lisp方言だった(POP-2のような他の言語も多値を提供した)。 - レコード構造定義機構であるDEFSTRUCT(Interlispのレコードパッケージ と比較せよ)。 - スペシャル変数上のクロージャ。これらのクロージャは、Schemeでのそれ のようなものではなかった; 環境によって捕えられた変数は、プログラマ によって明示的にリストされなければならず、クロージャの呼び出しは、 SPECIAL変数を保存した値へ束縛することを必要とした。 - オブジェクト指向の、多重継承を持つ非階層的プログラミングシステムで あるFlavorsは、Howard CannonとDavid A. Moonによって設計され、Lisp Machineプログラミング環境の一部に統合された(特に、ウィンドウシステ ムがFlavorsを使って書かれた[Weinreb, March 1981])。 - 汎変数のための機構であるSETF 以下のフォームの列がLisp machine Lispインタプリタへ渡されると考えよ う。最後のフォームは7ではなく3を戻す。なぜなら、スペシャル変数yは、 Lisp machine Lispで書かれているfunの中のクロージャを呼び出すことによっ て、その古い値へリセットされるからである: (defun foo (x) (+ (bar) x)) (defun bar () y) (setq fun ((lambda (y) (closure '(x) (function foo))) 3)) (setq y 7) (funcall fun 0) => 3 ;not 7 Common Lisp - 後の最もポピュラーなLispの方言 - の至るところでのSETF の使用は、Symbolics ZetalispやMacLispを通じてMIT Lisp-Machine Lispの影 響まで、そしてGreenblattの提案を通じてPeter Deutschや、それゆえAlan Kayまでたどられ得る。 統一したアクセスの扱い - 状態の読み込みや書きだし - は、Common Lisp を、仮にそうでないとしたものよりも統一したものにした。(CARのような)読 み込み関数と、(RPLACAのような)別の書きだしあるいは更新関数の両方を覚え る必要はもはやなく、引数の順序(RPLACAに対しては、ドットペアか、そのcar に対する新たな値か、どちらが先に来るのだったか?)を覚える必要ももうない。 読み込み操作の一般のフォームが(f . . . )である場合、書き出しのフォーム は(setf (f . . . ) newvalue)であり、それが、データの読み書きについてプ ログラマが知る必要がある全てである。 CLOSでは、このアイディアはメソッドへ拡張された。リーダとして動作する ように指定されたメソッドMがあり、(M object)のように呼び出される場合、 (setf (M object) newvalue)として呼び出されるライタメソッドを定義できる。 CLOSがこのイディオムにとてもうまく当てはまることは驚くべきことではな い。Alan Kayが、1973年頃このアイディアに対するインスピレーションだった とすると、彼は初期のSmalltalkへかかわっている最中だった。読み込みと書 き出しは、どちらもオブジェクトがサポートできるメソッドであり、Kayのビ ジョンのLisp版にCLOSが適応したことは、オブジェクト指向のアイディアの起 源の単なる再発明だった。 2.6.2 Xerox Lisp Machines: 1973-1980 Altoは、1973年に開発されたマイクロコード可能なマシンであり[Thacker, 1982]、InterlispやMesa[Geschke, 1977]のような他の言語を用いて、Xeroxで パーソナルコンピューティングの実験に使われた。Interlisp環境のAlto版は、 1975年頃にPARCとスタンフォード大学で最初に使われ出した。 Altoは、標準で64Kの16ビットの語のメモリを装備し、256K語まで拡張可能 であった。それは、単一ユーザコンピュータにとっては極めて大きかったが、 それでもPDP-10のメモリのたった半分だった。[Deutsch, 1973]の中でDeutsch によって論じられた全てのコード密集トリックを用いてすら、そのマシンは、 大きなInterlisp環境のためにはパワー不足であることがわかっていたので、 ユーザによって広く受け入れられることはなかった。 Altoは、最初のSmalltalk環境 - "中間Dynabook" - を作るためにも使われ、 ここでは、それは比較的成功した。 1976年、Xerox Parcは、Dorado(あるいはXerox 1132)と呼ばれるマシンの設 計を開始した。それは、Altoを置き換えるように設計されたECL(エミッタ結合 論理(Emitter Coupled Logic)、当時の高速なデジタル論理実装技術)マシンだっ た。1978年に利用可能だったプロトタイプは、全てのAltoソフトウェアを実行 した。再設計は1979年に完了し、かなりの数が、Xeroxの中と、スタンフォー ド大学のようなある種の実験的なサイトで使われるために作られた。Doradoは、 コンパイラによって生成されたバイトコードを解釈するように特に設計され、 これが、DoradoがAltoのソフトウェアを実行した方法である。Doradoは、基本 的にエミュレーションマシンだった。 Interlispは、Interlisp仮想マシンモデル[Moore, 1976]を用いて、このマ シンに移植された。Interlispを実行するDoradoは、単一ユーザのInterlispを 実行するKL-10よりも速く、商業的に広く利用可能にされたならば、とても魅 力があるLispマシンだと証明されただろう。Doradoはプロトタイプとして設計 され、FCC RF放射要求をパスすることは決してできず(???これが真実かどうか チェックすること)、その使用は、Xeroxのサイトと、スタンフォード大学のよ うないくつかの特別な実験的なセッティングに限られた。 Interlispは、Dolphinと呼ばれるもっと小さくて安いマシンへ移植された。 Dolphinは、1970年代終わりにLispマシンとして商業的に利用可能になった。 Dolphinの処理性能は、Altoのそれよりもよかったが、そのマシンがLispエン ジンとして真に成功することは決してないくらいに悪かった。 1980年代初め、XeroxはDandelion (1108)と呼ばれる別のマシンを作った。 それはDolphinよりはかなり速かったが、それでもDoradoほどは速くなかった。 これら3つのマシンの名前は全て文字"D"で始まったので、それらは集合的に"D マシン"として知られるようになった。 全てのXerox Lispマシンは、インクリメンタルなリファレンスカウントガー ベジコレクタ[Deutsch, 1976]を使った: 記憶域が割り当てられるたびに、ゴ ミ集めのプロセスの数ステップが実行されただろう。従って、単位時間にゴミ 集めがする仕事は、不十分で限られた量だった。 1970年代の終わり頃、BBNもJerichoというマシンを作り、Interlispエンジ ンとして使われた。それは、BBN内部のものであり続けた[?]。 初期のLisp Machineの歴史の分析 MIT Lispマシンプロジェクトは、MacLisp, MDL, そしてConniverによって例証 される多様化の統合を表わしていた。いくつかの新たな拡張と、他の源からの 改造がなされた。 受容グループはまだ局所的な研究者だったが、1980年代の間にそれは変わる ことになった: 新たな受容グループは、商業的開発者と企業の研究所になるこ とになった。受容の戦いは、受容可能なコンピュータと受容可能なワークプロ セスの要因の周りに集中することになった。ワークプロセスに含まれるものは、 本質、コスト、そしてLispプログラマの利用可能性である。 Xerox Lispマシンは移植性を示したが、それは言語が本質的には停滞してい るときに起こることである。Interlispの受容は、今ではマシンの選択次第で 決まるだろう。受容可能なマシンに対する2つの真の競争者がある - VaxとDマ シンである。その成功がVaxに依存しているどのLispも、1980年代を生き残ら ないだろう。それは、1980年代始めには、DマシンやMIT由来のLispマシンとの 間の競争になり、1980年代始めに始まった大統合が、ゲームの性質を完全に変 えるだろう。MacLispとInterlispはどちらも間もなく死に、純粋な形式での LispマシンLispもそれらの道連れになる。 Lispマシンの存在を通じて、Lispの印が興隆していたことを理解することが 重要である。受容グループもまもなく興隆し、Lispマシン設計者と開発者の注 意深い手引きの元で、テクノロジーが大成功するだろうという感じがあった。 莫大な量のベンチャー資本を消費して、企業がAIやLispテクノロジーの波に乗 ろうと形成されるだろう。これは最初の - そして今日まで唯一の - FORTRAN マシン要塞に登ったもっともらしい攻撃だった。我々が知っている通り攻撃は 失敗し、その理由を見つけることは、コンピューティングの専門家としての、 また人間としての我々自身について多くのことを教えるかもしれない。 前のアーキテクチャのアドレス空間制限から自由になったので、全てのLisp マシン企業は、非常に拡張したLisp実装を生み出し、それらのプログラミング 環境へ、グラフィックス、ウィンドウ能力、そしてマウスでの対話能力を加え た。Lisp言語自身も、とりわけMIT Lisp Machineでは、機能の数や複雑さの点 で発達した。これらのアイディアのいくつかは他のところを起源としているが、 それらのLispコミュニティへの採用は、アイディア自身の印によってと同様に、 Lispマシンの成功と印によって駆動された。 それにもかかわらず、多くのユーザにとっては、価値は結局ソフトウェアに あり、それを可能にするハードウェアテクノロジーにではない。Lispマシン企 業は、1980年代の終わりに苦境に入ったが、おそらく、この事実の帰結を完全 には理解していなかったためだろう。汎用ハードウェアは、結局、再びLispを サポートするのに十分なほど良くなり、そのようなマシン上のLisp実装は、事 実上競争し始めた。 2.7 IBM Lisp: Lisp360とLisp370 最初のLispはIBMコンピュータ上で実装されたが、IBMは、1960年代後半、2つ の理由のためにLispシーンから消えかけていた: MITとDECの間の良好な協力と、 MITとIBMの間の特許論争である。 1960年代の初め、Digital Equipment Corporationは、MITがコンピュータに 対して持つニーズや、Lisp実装を助けるために加えられる機能について、MIT と議論した。7094と同様に、各36ビットの語は、ドットペアを形成する2つの アドレスを保持できたが、PDP-10では、各アドレスは15ビットではなく18ビッ トだった。PDP-10の半ワードの命令は、CAR, CDR, RPLACA, そしてRPLACDを特 に速く、そして実装しやすくした。スタック命令と、スタックに基づく関数呼 び出し命令は、Lisp関数呼び出しの速度を改善した(MIT AI Laboratoryは、最 初の - あるいは2番目の - PDP-6を受け取り、その後継のPDP-10によって置き 換えられるまで、研究所の頼みの綱の計算エンジンだった)。 さらに、1960年代の初め、IBMとMITは、誰がコアメモリを発明したかを論争 し、IBMは、MITに対してその特許を施行すると主張した。MITは、以前ほど広 範囲にIBM装置を使うことをやめることで返答した。これは、特にLispとAIに 対して、代わりにDEC装置を使うことにさらにはずみをつけた。 それにもかかわらず、LispはIBM 360のためにIBMで実装され、Lisp360と呼 ばれた。IBM 370が出荷されたとき、Lisp370の実装が始まった。Lisp370は、 後にLisp/VMと呼ばれた。 Lisp360は基本的にバッチLispであり、大学での授業のためにかなり広く使 われた。 Lisp370は、SECDモデル[Landin, 1964]で表現された形式文法に基づく核 Lispの定義から始まった。この定義は、1、2ページに収まる。Lisp370プロジェ クトは、ニューヨークYorktown HeightsのIBM Thomas J. Watson Research Centerで、Fred Blair(SECD定義の開発者)の指揮下で行なわれた。グループの 他のメンバーは、Richard W. Ryniker II, Cyril Alberga, Mark Wegman, そ してMartin Mikelsonsを含んでいた; 彼らは主に、彼ら自身や、SCRATCHPADグ ループやYorktownのいくつかのAIグループのような2、3の研究グループに仕え た。 Lisp370は、スパゲッティスタックに似たテクニックを用いて、レキシカル 変数とスペシャル変数の両方の上でのクロージャと同様に、スペシャル束縛と レキシカル束縛のどちらもサポートした。スペシャル値セルの実装は、実際の 値に対するキャッシュの形式を採用した。値セルは、それに対して束縛が正当 であるような制御木の枝を指定する確認セルとペアにされた。不正なときは、 現在のスタックフレームからの検索が、正しい値と確認をセットするために行 なわれた。このアルゴリズムは、1976年の夏に、Richard GabrielとWilliam Scherlisのいくらかの補助のもと、Allen Brown(以前MITでSussmanの教え子だっ た)によって開発された。Jon L Whiteは、1977年をYorktown Heightsで Lisp370上で働いて過ごし、それからMITへ戻った; IBMでの彼の経験は、その 後のMacLisp開発や、NIL方言にいくらか影響を与えた。 Lisp370は、ハードコピー端末と、どこにでもある3270キャラクタディスプ レイ端末のどちらでも動作するように書かれた、Interlispに似たプログラミ ング環境を持っていた。遅い端末を念頭に開発され、多くのIBMメインフレー ムの対話の半二重的性質は同じような感じを持っていたので、Interlisp-10モ デルは理想的だった。1976年の夏の間、Gabrielは、彼がStanford AI Labで MacLispのために書いた環境(この環境自身が、1974年にイリノイ大学の Co-ordinated Science Labで、彼がMacLispのために書いたものの改訂版であ る)の複製として、この環境の最初のバージョンを書いた。後に、Mark Wegman とYorktownの彼の同僚が、スクリーンに基づく - 行に基づくものではなく - 対話と編集を含むようにこの環境を拡張したが、まだs式に基づく編集や、 Gabrielが組み立てたもっと原始的なシステムのその他の本質的な特徴を保っ ていた。 よい処理性能や、コンパイルと実行環境の分離(それは別々のLispイメージ を使うことで達成された)のような、下にあるLispシステムへの改善がなされ た。 いくつかのCommon Lispを含む他のLispが、後に360/370ラインのコンピュー タに現れた。IBM 370上に現れた最初のCommon Lispは、Intermetricsによって 書かれ、素晴らしいコンパイル技術を特長としていた。しかし、そのLispはう まく構築されてはおらず、Lisp界に大きなインパクトを与えることは決してな かった。何年か後、Lucidは、IBMとの契約の元で、そのCommon Lispを370へ移 植した。IBMは、Common Lispの方を選び、1980年代末にLisp370のサポートを 止めた。 分析 Yorktown Heights Lispは、T. J. Watson Research Laboratoryの局所的な受 容グループの周囲の多様化に基づいていた。特に、Fred Blair, Richard W. Ryniker II, Cyril Alberga, Mark Wegman, そしてMartin Mikelsonsから 成るこのグループは、主に彼ら自身や、ScratchpadグループやいくつかのAIグ ループのような、2、3の研究グループに仕えた。 このグループには、多様化の方向に影響する訪問者がいた。たとえば、MIT AI LabのAllen Brownは、1975年から1978年までYorktownで働いたし、Jon L Whiteは1977年の間そこで働いた。Richard Gabrielは、Lisp370プログラミン グ環境で、1976年の夏の間働いた(彼の体は、カリフォルニアのサンノゼのIBM 研究センターにあったのだが)。 受容は局所的で論争にはならなかったが、多様化を伴う統合は、他の環境か ら来た従業員からの影響によって決定された。リストアップした人たちに加え て、Mark Wegmanは、他の人たちよりも後にチームに加わっており、彼の到着 は、Gabrielが導入したものよりも広いプログラミング環境のビジョンと合致 した。 370は、商業化の自然なターゲットとして以外には、どのような印も決して 持たなかった。(ある期間)非常にポピュラーだったCommon Lispでさえ、370が、 Lispの成功の中で重要なプレーヤーとみなされることは決してないことがわか るだろう。Lisp370は確かに素晴らしい開発環境を提供したが、それでも、 Lispに対する自然な受容グループの誰も、370が、有用な環境を持つ適切なマ シンであるとは考えなかった。 これは、興味深いポイントを持ち出す。Intellicorp, Inference, そして Teknowledge のようなAI企業は全て、Fortune 500企業、とりわけ馬車馬とし て370を使っている企業をターゲットとしていた。各AI企業は、自身の運命は、 製品を370上に載せることができたときにだけ上がるだろうと予測した。しか し、Aionを例外として、このことがAI企業へ大きな違いになることは決してな かった。Aionは、より控え目な、顧客のニーズを若干もっと直接に狙った製品 の集合を提供した。 他の企業の多くは、特定の問題を解くためにプログラム可能な、大きなエキ スパートシステムシェルを作った。これらの解決策は、通常、作るためにAI企 業の助けを必要とした。 AI企業によって作られたLispに基づくAI解決策は、その解決策がLispで書か れていたために、大きなインパクトを持つことに失敗したと主張することがで きるかもしれない。しかし、解決策が十分だったら、下にある言語による違い はないだろう。おそらくAIの観点からは、AI自身が、AI企業がそうであるべき だと信じていたような印を持たなかったので、これらの種類の解決策は受け入 れられなかった。 または、おそらく、印はそこにあったのだが、無関係なのである。印は先端 であり、いくつかの組織は、先端にではなく、安全なコースに興味がある。こ れらの企業は、IBM PCを購入し、同様にIBM 370を購入する。Macintoshの印は 彼らに影響を与えず、AIの印も同様である。印は、それを持つ物と、それを欲 する人との間の関係であることを思いだそう。 2.8 Scheme: 1975-1980 Schemeとして知られているLispの方言は、もともとは、計算モデルとしての Carl Hewittのアクタ理論のいくつかの面を自分たちに詳説するための、1975 年の秋の間のGerald Jay SussmanとGuy Steeleによる試みであった。Hewittの モデルはオブジェクト指向(そしてSmalltalkに影響されていた)だった; 全て のオブジェクトは、計算的には、メッセージを受け取って反応できるアクティ ブな実体であった。オブジェクトはアクタと呼ばれ、メッセージ自身もアクタ だった。アクタは、任意の多さの知識を持つことができるだろう; すなわち、 他のアクタ「について知っている」(Hewittの言葉)ことができ、それらへメッ セージを送ったり、メッセージ(の一部)として知識を送ったりできるだろう。 メッセージパッシングは、単に相互作用の手段だった。関数型相互作用は、継 続の使用でモデル化された; "factorial"という名前のアクタに、数5と、最終 的に計算された値(おそらく120)を送るための別のアクタを送るかもしれない。 SussmanとSteeleは、Hewittの論文と言語設計からのモデルの帰結のいくつ かを理解することにいくらか困難があったので、実験するために、アクタ言語 のおもちゃ実装を構築することに決めた。作業環境としてMacLispを使い、小 さなLispインタプリタを構築して、アクタ作成とメッセージ送信のために必要 なメカニズムを加えることにした。そのおもちゃLispは、原始アクタの内部の 振る舞いを実装するために必要なプリミティブを提供するだろう。 Sussmanは、ちょうどAlgol [Naur, 1963]を学んだところだったので、レキ シカルスコープのLispの方言で始めることを提案した。そのようなメカニズム が、アクタに対する知識を追跡するためにいずれにしても必要だろうと思われ た。これは、アクタと関数が、ほとんど同じメカニズムで作られることを許し た。語lambdaで始まるフォームを評価すると、現在の変数辞書引き環境をとら えて、クロージャを作る; 語alphaで始まるフォームを評価すると、現在の環 境は同様にとらえるが、アクタを作る。メッセージパッシングは、関数呼び出 しと同じ方法で文法的には表現し得る。アクタと関数の差は、applyとして伝 統的に知られているインタプリタの部分で発見されるだろう。関数は値を戻す だろうが、アクタは決して戻らない; その代わりに、知っている別のアクタで ある継続を典型的には呼び出すだろう。従って、ある人は以下の関数を定義す るかもしれないし、 (define factorial (lambda (n) (if (= n 0) 1 (* n (factorial (- n 1)))))) 同等のアクタを定義するかもしれない。 (define actorial (alpha (n c) (if (= n 0) (c 1) (actorial (- n 1) (alpha (f) (c (* f n))))))) この例では、外側のalpha式を呼び出すメッセージの中で渡されるcとnの値は、 内側のalpha式によって作られる継続アクタの知識になることに注意しよう。 actorialの再帰呼び出しは値を戻すことを期待されないので、この継続は明示 的に渡されなければならない。 SussmanとSteeleは、このおもちゃアクタ実装にとても満足し、Plannerと Conniverの伝統の中で別のAI言語として発達するかもしれないと期待して、 "Schemer"と名付けた。しかし、ITSオペレーティングシステムはファイル名に 6文字制限があったので、名前は単に"Scheme"へ切り詰められて、その名前が 定着した。 その後、重大な発見があった - それは、我々にとっては、言語設計での実 験の価値を例証するものである。applyのためのコードを検査しているとき、 いったん正しく動作するようにさせたら、SussmanとSteeleが発見して驚いた ことには、関数呼び出しに対するapplyの中のコードと、アクタ呼び出しのた めのコードが同一だったのである! 関数やアクタの作成のためのコードのよ うな、インタプリタの他の部分をさらに検査すると、この洞察が確認された: 関数は値を戻すように意図され、アクタはそうではないという事実は、実装の どこにも違いを及ぼさない。違いは、純粋に、それらの本体をコード化するた めに使われるプリミティブの中にあった。下にあるプリミティブが値を戻す場 合、ユーザは値を戻す関数を書ける; 全てのプリミティブが継続を期待する場 合、ユーザはアクタを書ける。しかし、lambdaとalphaメカニズム自身は同一 であり、このことから、SussmanとSteeleは、アクタとクロージャは同じ概念 だと結論した。Hewittは、この判断に後に同意したが、彼の理論の中の2つの プリミティブアクタの型、すなわち(変更可能な状態を持つ)セルと(独占的な アクセスを強いる)シンクロナイザは、同等のプリミティブ拡張なしのレキシ カルスコープの純粋Lispでは、クロージャとして表現できないと注釈した。 SussmanとSteeleは、この発見をしたことに対して、アクタモデル - あるい はLisp - を低く考えたのではなかった; 実際、Schemeは、なお次のAI言語と して良いだろうし、データと制御構造についてその頃流布していたアイディア の多くを、もっとずっと単純なフレームワークでとらえているように彼らには 思えた。Schemeに関する最初のレポート[Sussman, 1975b]は、概念に1つとい う、最少のプリミティブ構成を用いる、たいへん切り詰めた言語を記述してい る(1つで良いときになぜ2つ取る?)。関数コンストラクタlambda、不動点オペ レータlabels、条件if、副作用aset、継続アクセサcatch、関数適用、変数参 照があり、他はそれほどなかった。シンボル、リスト、そして数のようなプリ ミティブデータ構造は各種取り揃えられていたが、これらと、これらに関する オペレーションは、理論的な必要ではなく、実用的な便宜と考えられた。 1976年に、SussmanとSteeleは、フレームワークとしてSchemeを用いてプロ グラミング言語意味論を探求する2つの論文を書いた。Lambda: The Ultimate Imperative [Steele, 1976b]は、広範な種類の制御構造のアイディアがScheme でどのようにモデル化され得るかを例証した。そのモデルのいくつかは、 Peter Landin, John Reynolds、その他による初期の仕事[Landin, 1965; Reynolds, 1972; Friedman, November]を利用した。その論文は、一部はチュ ートリアルを意図しており、一部は制御構造を集めて整理したカタログだった (この論文は、"Lambda: The Ultimate X"論文の長いシリーズの最初のものと しても有名であり、より広いプログラミング言語コミュニティで"X Considered Harmful"のタイトルがそうであるように、Lispコミュニティでは 良く知られた連続ギャグである)。Lambda: The Ultimate Declarative [Steele, 1976a]は、リネームのための構造物としてのlambdaの性質に集中し た; また、オブジェクト指向プログラミング一般と特にアクタをクロージャに 関連させて、SchemeとHewittのPLASMA(4節を参照)のもっと広範な比較を提供 した。これは、この論文がいくつかの詳細を概説した、Schemeのための実用的 なコンパイラを構築するためのテクニックの集合も提案した。この論文は学位 論文の提案だった; その結果の学位論文は、RABBIT [Steele, 1978a]と呼ばれ るSchemeコンパイラについて論じた。Mitchell WandとDaniel Friedmanは、同 じ頃にインディアナ大学で類似の仕事を行なっており[Wand, 1977]、この期間 中に、SussmanやSteeleと論文を交換した。 Steeleは、ACM National Conferenceに対しても、手続き呼び出しの末尾再 帰と最適化に対するラムダ算法の意味について論じる論文を提出した[Steele, 1977d]。Lispコミュニティの外の言語の実装上の実際の効果は、後から考える と、完全にとるに足らないものに思われる。しかし、ある聴衆は、頭上のスラ イドに示される例の中の手続き名の選択を彼がどれほど楽しんだかをSteeleへ 述べた。そのとき、Steeleは、全世界が、標準の臨時の語としてFOOやBARを使 うわけではないという実状に襲われたのだった。 続いて、SteeleとSussmanは、改訂Scheme報告書(revised report on Scheme)[Steele, 1978c]を書いた; その報告書のタイトルは、Algolへの賛辞 を意図していたが、別のますますばかげた一連のタイトルを次々に引き起こし た[Clinger, 1985a; Clinger, 1985b; Rees, 1986; ?]。その後まもなく、そ のタイトルがフーガの技法の冗談である派生的な研究論文を書き、さまざまな 変奏を伴う多数の小さなLispインタプリタを説明した。これは、土曜日の自宅 でのSussmanの研究の中でほとんどが書かれた。Steeleは、ボストンの交通を 巧みに回避しながら、午前中ずっと自転車をこいだものだった; それから、彼 らはお茶を巨大なポット1つ分作り、議論とMITへのダイヤルアップ回線上での タイプを交互に行ないながら午後を過ごしたものだった。その研究論文は決し て終わることはなかった; Zero, One, そしてTwoの部分だけが出版された [Steele, 1978b]。Part Zeroは、再帰方程式上にモデル化された、小さな一階 のLisp方言を導入した。Part Oneは、データとしての手続きについて論じ、レ キシカルとダイナミックな束縛を探求した。Part Twoは、状態の分解と、副作 用の意味を扱った。Part Threeは、評価の順序(値による呼び出し (call-by-value)対名前による呼び出し(call-by-name))をカバーすることになっ ており、Part Fourはメタ言語、マクロプロセッサ、そしてコンパイラをカバ ーするように意図されていた。これらの最後の2つの部分が決して書かれなかっ たことは大した損失ではない。なぜなら、これらのトピックは、他の研究者た ちによって、まもなく十分に扱われるからである。インタプリタの技法は、 Scheme地下組織ではいくらかの悪名を馳せたが、ACMジャーナルからは拒絶さ れた。 これら全ての論文の大部分は新しくはなかった; それらの主要な貢献は、理 論家によって使われるモデル(学習するアクタとラムダ算法)と、実務家(Lisp 実装者やユーザ)の間のギャップを橋渡ししたことだった。Schemeは、表示的 意味論のような領域での理論的な貢献を、もっとずっとLispハッカーにアクセ スしやすくした; また、理論家による実験のための、便利に使えるプラットフォ ームを提供した。多くの数のサイトや、広範な種類のマシン上でSchemeをサポ ートするために、中央集権的な実装グループは必要なかった。Standard Lisp に似ているが、よりいっそう小さく単純であり、Schemeは、非常に短時間に、 いくつかの他のLispシステムの上に築くことができた。ローカルな実装や方言 が、多くの他のサイトで生じた(1つの良い例はインディアナ大学のScheme 311 である[Fessenden, 1983; Clinger, 1984]); 誰かが、ポータブルなスタンド アローンのSchemeシステムを生み出す真剣な試みを行なう数年前のことだった [?]。 Scheme実装上の広範な仕事は、Jonathan Rees, Norman Adams, その他によっ て、エール大学、後にMITで行なわれた。これは、Tとして知られるSchemeの方 言になった; この名前は皆に良いジョークだった。なぜなら、Tは、ほぼNIL方 言がMacLispに対してそうだったように、Schemeに対するものだったからであ る。そのゴールは、特に効率的な実装を持つ単純な方言になることだった [Rees, 1982]: Tは、小さい核言語に集中し、複雑な機能はないので、学びやすい… 我々 は、完全に正しいとは感じなかった機能をサポートすることを止めた。T の省略は重要である: 我々は、Common Lispの複雑な引数リスト文法、キ ーワードオプション、そして1つの関数上にオーバーロードされる多数の 機能を避けた。後で後悔するかもしれない何かを今実装するより、何かを 後で一般化することはずっと易しい。全ての機能は、スタイル上の純粋性 と一般性に対して、注意深く考慮された。 従って、Tの設計は、Lispの伝統からだけではなく、SteeleとSussmanが物事を きれいにするよりも伝統に頼った初期のバージョンのSchemeの個所からの意識 的な断絶をも示した。組み込み関数の名前は規則的にされた。Tは、伝統的な -P接頭辞を、疑問符の普遍的な使用で置き換えた; 従って、numberpはnumber? に、nullはnull?になった。同様に、それぞれの破壊的オペレーションは、感 嘆符で終わる名前を持った; 従って、appendの破壊版に対するMacLisp名であ るnconcはappend!になった(Muddle [Galley, 1975]が、述語を示す疑問符の使 用を導入し、Sussmanは、彼の文書のいくつかで何年間もこの慣習を使った。 Interlispは、MacLispよりも一貫した破壊的オペレーションのラベル付けのシ ステムを持っており、接頭辞として文字dを用いた)。 Tは、(UnixとVMSの両方の元での)VAXとApolloワークステーションを当初タ ーゲットにした。システムの大部分はTで書かれ、TコンパイラであるTCによっ てブートストラップされた。特に、評価器とガーベジコレクタはTで書かれて おり、マシン言語でではなかった。Tプロジェクトは、S-1 Lispコンパイラ [Brooks, 1982b]の1バージョンで始められ、かなりの改善がなされた; その仕 事の中で、彼らは、S-1コンパイラと、RABBIT [Steele, 1978a]の元の報告の 中にいくつかのバグを確認した。S-1 Lispコンパイラのように、それは、主流 のコンパイラ研究、とりわけBLISS-11コンパイラ[Wulf, 1975]上のWulf他によ る仕事からの最適化戦略に大いに依存していた。 ORBIT [Kranz, 1986]と呼ばれたTコンパイラの第2世代は、主流のホストと、 Lisp特有の最適化戦略を統合し、結果として真の製品品質のScheme環境になっ た。RABBITは、"継続渡しスタイル"(CPS)へソースからソースへの変換を行な うことで、Lispコードを変換する原理にまとめられた; ORBITは、変数への代 入を扱うように、この戦略を一般化して拡張した。レジスタアロケータは、 fork, join, そして手続き呼び出しでのレジスタ使用を最適化するために、ト レーススケジューリングを用いた。ORBITは、Lisp以外の言語で書かれた手続 きへの呼び出しもサポートした(これは、CMUや他の場所での、Common Lispの ための一般的な"外部関数呼び出し(foreign function call)"の開発の努力と 同時期だった)。 2.9 Common Lispの前ぶれ 1981年の春、状況は以下の通りだった。2つのLispマシン企業が、MIT Lispマ シンプロジェクトから出た: Lisp Machines Inc. (LMI)とSymbolics, Incであ る。前者は主にRichard Greenblattによって、後者はDavid A. Moonを含むもっ と大きなグループによって設立された。どちらも最初は、2番目のMIT Lispマ シンであるCADRを製造し、会社によってなされた全ての改善を戻すことを含む 協定の元で、それぞれがLispマシンソフトウェアをライセンスした。まもなく Symbolicsは、3600と呼ばれることになる、次のLispマシンの設計と作成に乗 り出した。その言語Lisp-Machine Lispは、1978年に発行された最初の定義か らたいへん進化しており、種々の新たな機能、とりわけFlavorsと呼ばれるオ ブジェクト指向拡張を獲得していた。 Xerox LispマシンDolphinとDoradoはInterlispを実行しており、多くは西海 岸にある研究所で使われた。BBNは、Jerichoと呼ばれるInterlispマシンを構 築中であり、VaxへのInterlispの移植が進行していた。 MITでは、あるプロジェクトが、VaxとS1コンピュータ上で、NILと呼ばれる MacLispの子孫の定義と実装を始めていた。 CMUでは、Scott Fahlmanと同僚と生徒が、Spiceマシン - 科学的で個人的な 統合コンピューティング環境(scientific Personal Integrated Computing Environment) - 上に実装されることになっていた、Spice Lispと呼ばれる MacLispに似たLispの方言の定義と実装を行なっていた。 2.10 初期のCommon Lisp この時点で、Lispコミュニティでの統合がなかったら、Lispは死んでいたかも しれない。ARPAは、種々の、不要に競合して根拠なく異なるLispプロジェクト に出資することに興味はなかった。そして、商業的な活動の舞台はなかった - その頃は。 2.10.1 MacLispの混沌から 1981年4月、ARPAは"Lisp Community Meeting"を招集し、そこで実装グループ は、Lispの将来について議論するために一堂に会した。ARPAは多くのAI研究を 後援し、彼らのゴールは、その研究コミュニティでのますます多様な集合にな るLisp方言の傾向をくいとめるために何をなし得るかを見ることだった。 ARPAミーティングの前日、Interlispコミュニティの一部は、種々のマシン 上での健全なInterlispコミュニティの状況をどのように示すかを議論するた めに集まった。そのアイディアは、常に増加する異なるコンピュータのタイプ の数の上に存在する標準言語(Interlisp)と標準環境の視点をプッシュするこ とだった。 ミーティングの当日、Interlispコミュニティは、1つのゴールとミッション を持つ一貫したグループとしての自分たちを示すことに成功した。 MacLisp系列のグループは、逸話として最も良く説明され得る、ある方法で 行なった。各グループは立ち上がり、どこへ向かっていてそれはなぜかを示し た。いくつかの質問が、Interlispコミュニティと対比してはっきりしない MacLispコミュニティの方向について起こった。Scott Fahlmanは言った、 「MacLispコミュニティは混沌状態ではない。4つのはっきり定義された方向へ 進む、4つのはっきり定義されたグループからなるのだ。」笑い声が静まるま でにしばらくの休止があった[Steele, 1982]。 Gabrielは、ARPAミーティングの前日のInterlisp集会に出席し、ミーティン グでのMacLispコミュニティの見せ物も目撃した。彼は、MacLispグループ間の 違いが打ち勝ち難いものとは信じなかったので、グループ間のなんらかの種類 の協力のアイディアを売り込み始めた。 まず、彼はJon L Whiteに接近した。彼らが議論したアイディアは2つの部分 からなっていた: MacLispコミュニティのLispへの願望を統一しようとするこ と、そしてそれを契約の元でARPAに対して行なうことだった。このとき Gabrielは、NILを実装していたS1 Lispプロジェクトにいたので、Whiteとは自 然に密接な関係があった。彼らは、SRIのAI Labの長だったNils Nilssonとそ のアイディアについて議論し、そのアイディアに対して、より以上のサポート を協力して行なおうということに同意した。 次に、GabrielとWhiteはGuy Steeleに接近し、それからCMUでSPICE Lispプ ロジェクトと交際した。それらの3人 - Steele, White, そしてGabriel - は、 皆S-1 NILプロジェクトになんらかの関係があり、ARPAミーティングの次の日 にLawrence Livermore国立研究所へ行くところだった。彼らは、Gabrielのエ アコンのないVW bugの中、暑く、埃っぽく、長いLLNLへの道で、窓を下ろして 協力について議論した。彼らはFahlmanに接近することに同意した。 数ヶ月後、Gabriel, Steele, White, Fahlman, William Scherlis(CMUでの Gabrielの後の同僚), そしてRod Brooks(S1 Lispプロジェクトの重要人物)が CMUで会い、新たなLispのいくつかの技術的な詳細が議論された。特に、その 新たな方言は、以下の基本機能を持つことになった: - 完全なクロージャを含む、レキシカルスコーピング - Lisp-Machine Lispのような形式だが、おそらく単一の値を強いる状況 に対してなんらかの修正を用いる多値 - 値と関数のセルを分けるという意味でのLisp-2[Gabriel, 1988] (??節 を参照) - Defstruct - SETF - 複素数と有理数を含む極上の浮動小数点数(これは主にS-1 Lispの影響 だった) - Lisp-Machine Lispに似ている、複雑なラムダリスト宣言 - (NILで"flexures"と呼ばれる)動的クロージャはない 1.5日の技術的な議論の後、このグループは、CMUからそれほど遠くない、脂っ こいサブマリーンサンドイッチの店であるOakland Originalへ行った。昼食の 間と後、そのLispに対する名前の話題が上がり、NILやSPICE Lispのような明 らかな名前が提案されて却下され - あるグループにあまりに多くの、その他 には不十分な名声を与えるため - Yu-Hsiang Lispのようなあまり明らかでは ない名前も提案されて渋々却下された。 最高と感じられた名前は"Standard Lisp"だったが、別の方言がその名前で すでに知られていた。類似の語を探す中で、名前"Common Lisp"が浮かんだ。 Gabrielは、我々はエリート主義のLisp(Elitist Lisp)を定義しようとしてお り、"Common Lisp"は"凡人のLisp(Common Man Lisp)"にとても良く似た響きな ので、これは良い名前ではないと言った。 命名の議論は、別のピッツバーグ地区のイタリアンレストランPleasure Bar での夕食時に再開したが、誰にも運がなかった。 後に電子メールで、Moonは"我々がこの共通のLispをそう呼ぶなんでも (whatever we call this common Lisp)"に言及し、今回は、大変な悲しみと、 より良い名前を持てなかった驚愕の間で、それが選ばれた。 次のステップは、より多くのグループと接触することだった。キーは、最後 に接近されるであろう、Lispマシン企業だった。さらに、Gabrielはバークレ イのFranz LispグループとソルトレークシティのPSLグループを自発的に訪問 した。 GabrielのPSLとのミーティングは誠意のある有益なものであり、グループは、 議論に参加し、できるだけ結果を考慮することに同意したが、Common Lispの 努力は達成が難しく、とても多くのマシンで動作することを考えればPSLは明 白に有利なスタートを持っていると彼らが感じていることは明らかだった。そ れにもかかわらず、PSLグループのDon Morrisonは、そのプロセスの積極的な 関係者になった。Martin Grissは別個にコメントした(1982年1月21日、Guy Steeleへの私信、PSLマニュアルのドラフトを伴っているので、個人向けの挨 拶をもつフォームレターのようである): 我々は、PSLをStandard LISPの単なる単純な拡張にとどめることと、完全 に新たな、よりモダンなLISPの実装である別の端の間で引き裂かれている。 (LISP Machine, Spice LISP, NIL, そしてS-1コミュニティからの)新たな Common LISP方言の開発者との交流や、この努力への起こり得る参加は、 いくぶんバランスを変えるかもしれない。さしあたり、主にLISP Machine やCommon LISPマニュアル, Franz LISP, そしてUCI LISPに基づいて、PSL のためのモジュールを改変あるいは開発している。 Franzグループとのミーティングはもっと誠意がなく、強い関心がないこと が明らかだったが、グループのメンバーは、記述されるために、投票プロセス に加わった。 通常彼を特徴づけるものではない楽観主義の激発によって、GabrielはXerox Interlispグループに接近し、バークレイでよりも暖かい歓迎を受けたが、誰 か、おそらくBill VanMelleが、ほとんどオブザーバーとして、会議に出席す るだろうという兆候を残しただけだった。 良い理由はないが、知られるようになった通り、Lisp370グループがCommon Lisp Groupに加わるように招かれたことは決してなかった。その目的は大変明 白に国内向けに見えたので - ARPAコミュニティ内でのソフトウェア交換 - ヨ ーロッパのグループは全くコンタクトされず、これは後年に許されない侮辱と して見られることになった。 Gabrielは、Common Lispに対する計画について、ARPAへ話すことにいくらか の時間を費やし、彼らのサポートを得た。ARPAは、Spiceプロジェクトに費や していた資金のいくらかをCommon Lispに費やすことを許し、ARPANetを議論の ために使うこと、そうでなければ参加できなかっただろう人々へアカウントや ネットアクセスを提供することすら許した。 この草の根的努力に従事する人々やグループは、大体ARPANET上にいたので - 彼らはAI研究所に加入していたか、あるいは関係があった - 仕事の多くを、 電子メールを通じてネットワーク上で行なうと決定することは自然であり、電 子メールは自動的にアーカイブされた。実際、これは、ほとんど完全に電子メ ールによってなされた、最初の主要な言語標準化努力だった。 1981年の夏の間、BrooksとGabrielは、S-1 Lisp上でSteeleと共にCMUで働い ていた。この偶然のために、Common Lispに関する多くのミーティングや仕事 を行なうことができた。 SymbolicsとLMIとのミーティングは、1981年6月にSymbolicsで行なわれた。 SteeleとGabrielは、そのミーティングのためにピッツバーグからケンブリッ ジまで運転した。そのミーティングは、その方言の中には何があるべきかにつ いての深い技術的な議論と、なぜその新たな方言は良い事なのかについての政 治的な議論の間を行ったり来たりした。Lispマシン企業の視点からは、行動は Lispマシンと共にあり、より多くの場所で同じ方言が動作することへの興味は アカデミックなもののようだった。もちろん、同じ方言を多くの場所で走らせ ることにはビジネス的な理由があったのだが、ビジネス感覚をもつ人々はその ミーティングには参加しなかった。 最終的に、どちらのLispマシン企業もその努力に加わることを決定し、 Common Lisp Groupが形成された: Alan Bawden Richard P. Gabriel William L. Scherlis Rodney A. Brooks Joseph Ginder Richard M. Stallman Richard L. Bryan Richard Greenblatt Barbara K. Steele Glenn S. Burke Martin L. Griss Guy L. Steele Jr. Howard I. Cannon Charles L. Hedrick William vanMelle George J. Carrette Earl A. Killian Walter van Roggen David Dill John L. Kulp Allan C. Weschler Scott E. Fahlman Larry M. Masinter Daniel L. Weinreb Richard J. Fateman John McCarthy Jon L White Neal Feinberg Don Morrison Richard Zippel John Foderaro David A. Moon Leonard Zubkoff 1つの妥協として、定義される言語で書かれた全てのプログラムがその言語 族の中の全ての言語で動作するような、言語族を定義する価値があることに同 意した。すなわち、一種のサブセットが定義されることになったのだが、誰が そのサブセットを直接実装するかは明確ではなかった。 ドロップしたLispマシン機能は、Flavors, ウィンドウシステム, マルチプ ロセッシング(マルチタスキングを含む), グラフィックス, そしてlocativeな どだった。 その夏の間、Steeleは、Spice Lispマニュアルに基づく、最初のCommon Lispマニュアルの仕事を続けた。彼の最初の仕事は、Brooks, Scherlis, そし てGabrielによって手助けされた。Scherlisは、ほとんどはSteeleへの非公式 のアドバイスの形式で、型システムに特有の手助けを与えた。Gabrielは Steeleの家に住んでいたので、GabrielとSteeleは、課題について定期的に議 論した。 スイスチーズ版(Swiss Cheese Edition)と呼ばれるドラフト - 大きな穴が たくさんあったから - は、一部分は、その中で種々の代替案と、はい/いいえ の質問が提案されている投票用紙だった。電子メールベースの議論と投票のプ ロセスを通じて、最初の投票が通過した。これは、1981年11月の顔を合わせて のミーティングによって続けられ、そこでは、提出された質問の最終決定がな された。 これは、いくつか他の同様なドラフト/投票を伴う、別の洗練のラウンドに なった。その仕事の多くは、電子メールでの議論によって行なわれた。これら の議論は、ファイルアーカイブに保存された。MITのSloan Schoolでのある研 究は、コンピュータメールベースの意志決定と相互作用の調査にこれらのアー カイブを用いた。 この仕事のスタイルは、いくつかの興味深い結果を残した。人々は、実物で よりも電子メールでの方が無礼で率直になりがちである。ネットワーク越しに 行なわれる議論の多くは極めて勇ましかったが、自動的に書き下されるという 利点があった。曖昧な記憶や薄いインクに頼る必要はなかった。全てのメール は、1つの場所に自動的に格納されたので、失ったり置き忘れたりすることは なかった。 議論はしばしば、提案、議論、そして反対提案の形式だった。既存のソフト ウェアからのコード例、あるいは提案された新たな文法がしばしば交換された。 そして全ては、スピードを増したい、あるいは記録をさかのぼりたいと望む人々 によって、素早いレビューを受けやすかった。 このスタイルは、いくつかの欠点も持っていた。主要なものは、他の人々の 反応を観察できないこと、あるポイントが彼らを怒らせるかどうかが見られな いこと - それは、そのポイントが彼らにとって重要であることを意味する - だった。ある議論が、あまりに遠くまで行ってしまったり、ほとんどサポート がないことを見る方法はなかった。これは、時間が浪費されたことと、注意深 く手仕事で書かれた論拠が、何かをなすには必要とされることを意味した。 いったんそのプロセスが始まると、問題へのアプローチは、既存の方言の単 なる統合から - それはとるべき明白な方向だった - 正しいことを設計しよう とすることへ変わった。何人かの人々は、これは、いくつかの課題を再考する ための、そして、初期のLisp-Machine Lisp設計にとって大変重要だった、厳 密なMacLisp互換のゴールを捨てる良い時だという見方をとった。NILはシンボ ルでもCONSセルでもあるかのようないくつかの課題は、考え直されるべきだと 一般に同意されていたにもかかわらず、再考されなかった。 初め頃にやってきた1つの課題は述べる価値がある。なぜなら、それは、 Common Lispへの主要な攻撃の1つの核心であり、LispへのISOの仕事(2.12節を 参照)の間に始まった。これは、2つの面を持つモジュール化の問題である: (1)Common Lispは、コア言語とモジュールに分割されるべきかどうか、そして (2)いわゆるwhite, yellow, そしてredページへ分けるべきかどうかである。 これらのトピックは、議論の中に融合されたようにみえる。 "Whiteページ"は完全にマニュアルを指し、whiteページにある全てのものは、 それはCommon Lispだと開発者が主張するLispによって、ともかく実装されな ければならない。"Yellowページ"はロードされ得る実装独立のパッケージを指 し、たとえば、TRACEや科学技術関連サブルーチンパッケージがそれにあたる。 "red pages"は、デバイスドライバのような、実装依存のルーチンを記述する ように意図された。 それにもかかわらず、最初の疑問が、その課題を直接読むことによって持ち 出される: コアとモジュールへのCommon Lispの分割である。 これが、中心の層と、内側の層に依存する外側の層を持つ何層かに言語を分 割する提案を意味するととられた場合、Common Lispはもっと容易にサブセッ ト化でき、より小さなマシン上での明白な実装へ導いただろう。これは、安価 でたくさんの実装への必要性を満たしたかもしれない。これは、その言語の教 育バージョンを提供することも、より容易に可能にしたかもしれない。また、 ヨーロッパによる、そしてヨーロッパほどではないが日本による、ISOミーティ ングの間の強い攻撃を予防したかもしれない。 影響力のあるメンバーからの応答は啓発的である: 「これは奇妙に思える。 それに興味を起こさせよう。これらのモジュールは、実装の選択で随意なのか?」 「物事をモジュールにしておくことは良いゴールだが、完全に成功するとは期 待しないように。」「その分割は、小さな意味しかないだろう。」[?; ?] グループは、滑稽な白-黄-赤の区別にあまりに集中し、核言語/拡張言語の 区別には集中しなかった。これが異なって行なわれていたら、Common Lispの 将来も異なっていただろう。 注意深く延期されたのは、()がシンボルかどうかに関する決定だった。この 決定が、決定プロセス - 人々が感情的にはCommon Lispを受け入れ、彼らのエ ゴの一部を加えることを引き起こす - のほとんど最後まで残されてすら、議 論が生じたときには分裂を引き起こした。Symbolicsは、彼らの見解が受け入 れられない限りグループから脱退すると迫り、そのようになった。彼らのメッ セージの目立ったパラグラフは以下の通りである: 我々は、TとNILの問題について、何回か内部で議論を行なった。我々が完 全に新たな言語を設計している場合、他の多くのLisp内のいぼ(あるいは 美しいしみ)と同様に、きっとこれらについて再考するだろう(必ずしも変 えるわけではないかもしれないが、確実に再考するだろう)。しかし、Tと NILを今変更することにより得られる利益は、変換のコストに比べて極め て小さい。Symbolicsが容認できるこれらの問題への唯一の解決法は、現 状を維持することである。 これは、見たところ些細だが、人々に深い影響を持ち得る問題がいくつかあ ることを示している。 さらに3つのドラフトが作られた - 水切り器版(the Colander Edition, July 29, 1982)、レーザー版(the Laser Edition, November 16, 1982)、そし てメリーポピンズ版(the Mary Poppins Edition, ???)である。そのキュート な名前は、サブタイトルで説明されている: 水切り器: 前よりもっと多くの穴がある - しかし、それらはもっと小さい! レーザー版: 完全に一貫していることになっている メリーポピンズ版: あらゆる点で実用上は完璧 事実上、全ての決定は1983年初めまでに終えられたが、Digital Pressによる 速い出版の仕事をもってしても、書籍Common Lisp: The Languageが利用可能 になるまではほとんど1年かかった。 Common Lisp設計の期間、Guy Steeleは、CMUから休暇をとり、そしてTartan Laboratoriesに加わった。 Common Lisp Groupの宣言したゴールは、CLtL1 [Steele, 1984]から意訳さ れた以下の通りである: - 共通性: Common Lispは、それぞれが、異なるコンピュータのために MacLispの後継の実装を構築しているいくつかの実装グループの仕事に 焦点を合わせる試みから始まった。いくつかの実装の間の差異は、なん らかの非互換を強制し続けるだろうが、Common Lispは、これらの実装 のための共通の方言として役立つべきである。 - 移植性: Common Lispは、幅広いクラスのコンピュータ上で容易に実装 できない機能を除外すべきである。これは、たとえば宣言のように、普 通のハードウェアに対して一般的に必要な機能と同様に、一方では、マ イクロコードやハードウェアを必要とする機能を除外するのに役立つ (Lispをサポートするために特別に設計されたコンピュータとは反対に、 商業的に利用可能な、汎用の、"在庫品の"コンピュータを記述するため に、普通のハードウェアという語を使う)。 - 一貫性: インタプリタとコンパイラは、同じ意味論を表わすべきである。 - 表現性: Common Lispは、MacLispだけではなくInterlispも含む、種々 の方言からの最良の経験をえり抜くべきである。 - 互換性: Common Lispは、Zetalisp, MacLisp, そしてInterlispに、こ の順で互換であるように努力すべきである。 - 効率性: Common Lispに対する最適化コンパイラを書くことが可能であ るべきである。 - 力: Common Lispは、Interlispのようなユーザレベルのパッケージを書 くのに適した、良い、システム構築言語であるべきである。しかし、そ れらのパッケージは提供しない。 - 安定性: Common Lispは、ゆっくり、熟慮をもって進化すべきである。 Spice Lispは、Common Lispの努力に、2つの重要な貢献を提供した。1つは ドラフトCommon Lispマニュアルであり、それはSpice Lispマニュアル(とMIT Lisp Machine Manualsからも多くを借用した)から派生した。もうひとつは参 考の実装である。CLtL Iの出現後数年間、Spice Lispは、多くのCommon Lisp 実装に対する、文字通りソースとして役立った。コンピュータ企業は、フリー なソースコードをとり、それを彼らのコンピュータへ移植して、Common Lisp の基本レベルを提供したものだった。 時間と共に、企業は、ゼロから彼ら自身のCommon Lispを書くか、商用の Common Lisp企業と契約することを好んだが、前者は専門的知識を、後者はメ インテナンスを、それぞれ獲得するためだった。 後で、CLOSの開発は、フリーに利用可能な参考実装の存在から恩恵を受けた ことを見るだろう。 2.10.2 初期の不平 Common Lispの定義のプロセスは、全てがばら色ではなかった。終始、何人か の間には、強行採決された、あるいは物事がうまくいっていないという感じが あった。Interlispグループは、投票プロセスへインプットしたが、ある時点 で書いた: Interlispコミュニティは、この努力への我々の貢献がどうあるべきかに ついて、多少困惑している。Common Lispが、Interlisp風の言語機能をあ まり多くは組み入れようとしていないことは明らかである。我々は何をす べきだろうか? [?; ?] 問題の一部は、Lispマシン企業の強さと、Common Lisp Groupが彼らを群の 中にい続けさせる必要であり、それが彼らに、特に強いブランド力を授けた。 この点で、初期のCommon Lisp Groupの人々の一人は述べた: すまないが、現在のバージョン[draft]は、本当に以下のような感じを与 える。「さて、皆の喉を通るようにできる最も大きなLisp-Machine Lisp のサブセットは何で、それを標準と呼ぶか?」[?; ?] Lispマシンの人々には、満足することが難しいような議論の風味があった。 すなわち、彼らは大きなソフトウェアシステムでの経験があり、その領域では、 彼らが見つけた特定の解決策は、彼らによれば、正しいことである、という議 論である。実際の効果として、Common Lispは大きく大きくなっていった。 Common Lispのためのコンパイラを書かなければならない、普通のマシンの 人々の声が退けられたように考える人がいるかもしれないが、最も大きな声の 2人 - SteeleとGabriel - は、Common Lispの複雑さをくじく、パワフルなコ ンパイラを書く彼らの能力にうぬぼれていた。ある人は、彼らと、後にはMoon が、"十分に賢いコンパイラ(sufficiently smart compiler)"が特定の問題を 解決できるだろうというのをしばしば聞いた。すぐに、コアグループは、この "SSC"議論を定期的に引用するようになった(後に、数ヶ月の誠実な抵抗の中で、 それは軽いあざけりの語になった)。 そのコアグループは、結局は、CLtL Iの"著者"になった。Guy Steele, Scott Fahlman, David Moon, Daniel Weinreb, そしてRichard Gabrielである。 このグループは、言語仕様の文書を作ることと、そのレビューを指揮すること に対する責任を引き受けた。そのグループのために自らが採用した名前は "Quinquevirate"、あるいは、より非公式には、"5人のギャング(Gang of Five)"だった。 2.10.3 Common Lispの批評 1984年のLispと関数型プログラミングのシンポジウムで、Rod Brooksと Gabrielは、順番を乱して、"Common Lispの一批評(A Critique of Common Lisp)" [Brooks, 1984]という、素敵な開始論文を配った。GabrielとBrooksは、 そのビジネスプランが第一位のCommon Lisp企業になることである企業の創設 者だったので、これは、なおいっそう素敵だった。Fahlmanは、Gabrielによっ てなされたスピーチを聞いて、それを謀反と呼んだ。 この論文は、単に、一連のCommon Lispの批評の最初のものであり、それら の批評の多くはこの論文を引用した。この論文の高い点は、10年間の間、 Common Lispを悩ますことになった一連の問題を明らかにしている。 その著者は、以下が設計のゴールであるべきだと信じていた: 知的簡潔性: 言語は、平均的なプログラマが頭の中に入れられるほど十分 小さくあるべきである。 コンパイラの単純性: その言語に対する効率的なコードを生成するコンパ イラを書くことは、あまり大きくない仕事であるべきである。 実行時効率: オブジェクトコードは速く動作するべきである。 プログラミングの容易さ: 効率的なプログラムを書くことが、単純で楽し くあるべきである。 BrooksとGabrielは、Common Lisp設計の努力の間に実際に起こったことと、 これらの潜在的なゴールを対比する: 皆が大きなLispマシンを持つだろうというCommon Lisp Groupによる信 念が下にあった。 マイクロコーディングが型ディスパッチのコストを隠せるだろうという 過剰な期待があった。 共有配列のようなもののために明らかに必要な構成要素である、見えな いポインタのコストが無視された。 あまりに多くの言語のコストが、"十分に賢いコンパイラ"の議論で片付 けられた。 本質的に非効率なアイディア - 配列やベクタがその例である - の既存 の実装にあまりに重きが置かれた。 パス名や潜在的な数のような、輸送メカニズムを拡張し過ぎることにあ まりに多くの努力が費やされた。 Lispはシステムプログラミングのための正しい言語だという宗教的な信 念が、設計に組み込まれた。 輸送は目に見えないものであるべきである、そしてテキストエディタの ような大きく複雑なコード片は、ほとんど、または全く努力を必要とせず に、Common LispからCommon Lispへ移動すべきだという暗黙の信念があっ た。 妥協の精神が、あまりに多くの決定的に重要な事柄を未定義のままにし た。 Common Lispの汎用算術は、数とその必要な宣言のために、普通のハー ドウェアのプログラマが効率的な算術コードを書くことを難しくした。 算術オペレーションの不要な爆発的増加があった。 関数呼び出しが高価過ぎた。 期待されるコンピュータのサイズとパワーが不自然だった。 FORMATやSETFのようないくつかの良いアイディアは、あまりに遠くまで つれていかれた。 たとえば列関数のような、ライブラリであるべきだった物事が言語に含 まれた。 これらのテーマは、Common Lispの歴史の中で再発した - おそらく、最もひ ねくれた駄洒落の使い過ぎの愛好家ですら忍耐を損なうような、多数の "unCommon" Lispの出現である。各unCommon Lispは、Common Lispのいくつか の欠点へのもっと良いアプローチを示した。 公式に、あるいは非公式に、自身を"unCommon Lisp"であると宣言するLisp 方言の例は、Lisp370, Scheme, EuLisp, そしてmuLispである。これは、明ら かに、了解されているCommon Lispの欠点から遠ざかろうとする試みだが、そ れよりは明らかではないが、この語の使用は、主要なLisp方言としてのCommon Lispの明らかで真の強さを証明している。あるLispを、別の方言と対比して評 価することで定義することは、その別の方言の優越を認めることである("the unCorvette"としてMustangを宣伝するFordを想像しよう)。 全ての他の単一の現象よりも、この振る舞いは、Lispの多様化のキーとなる 構成要素の一つを例証する: 方言グループ間の極端な - ほとんど子どもじみ た - 競争である。 Lisp370とSchemeをすでに見た。EuLispは、Common Lispに対するヨーロッパ の反応であり、ヨーロッパのLispのための共通語として開発された。その主な 特徴は、Lisp-1(関数と変数の名前空間の分離がない)であること、完全に統合 されたCLOS(Common Lisp Object System)スタイルの総称関数タイプのオブジェ クト指向システムを持つこと、組み込みのモジュールシステムを持つこと、小 さい、組み込みのハードウェアや、教育的なマシン上でのそのLispの使用を促 進するために、複数の層で定義されていることである。その他の点では、 EuLispはCommon Lispに似ており、分離性ではなく共通性を持つ。EuLispの定 義は長い時間を要した; 1986年に始まり、1990年まで、ほとんど完全な言語仕 様を持つ最初の実装(インタプリタのみ)は利用可能にならなかった。それにも かかわらず、層にされた定義、モジュールシステム、そして始めからのオブジェ クト指向性は、新たなレッスンがLisp世界で学ばれ得ることを例証する。 これは複雑な期間である。明らかに統合があり、最初は意識的な統合だった。 統合は、2つの受容グループによって駆動される: ARPAコミュニティ(利他的効 果)とAI企業(商業的効果)である。利他的なグループは、コミュニティの善は 努力で駆動されていると感じているが、それを飛ばすのは、本当はLispマシン 企業の買い付けなのである。あるレベルでは、Common Lisp Groupは、Lispマ シンの人々は機嫌を伺われなければならないと知っているので、彼らとのあま りに多くの妥協がなされる。 Lispマシンは、努力を駆動する印を提供する。AIグループやARPAは日の出の 勢いであるので、その努力のための燃料がある。 何人かの新たなリーダーが現れる: 学究的でしばしば素朴なリーダーである Steele。若い関係者には特にカリスマ的なリーダーであるFahlman。ARPAや、 さまざまなグループを一列へ巧みに誘導する自称政治学の偉大な知性である Gabriel。魅力的でパワフルな思想家、静かでしばしば無礼、彼の議論はほと んど論駁することが不可能であるMoon。議論のあらゆる面に注意を払う思慮深 い傾聴者であるWeinreb。Jon Lのような古いリーダーたちは、わずかに背景へ 後退する。 McCarthyはほとんど、あるいは全く興味を示さないが、その間ずっと、 Gabrielを供する。これはMcCarthyに典型的なもので、彼はこのような詳細に はほとんど興味を持たない。 新たな実装のリーダーの出現がある。Gabriel, Steele, Brooks, Fahlmanで ある。Whiteは、XeroxとInterlispコミュニティに姿を消す。 Spice Lispは、Common Lispのための参考実装と思われ、いくつかのグルー プ - TI, PERQ, Siemens, DEC - は、彼らの最初のCommon Lispの基礎として それを使う。Spice Lispはフリーに利用可能であり、他のLisp方言のためのフ リーな参考実装としてのお膳立てをする。さらに、現れつつあるCommon Lisp のパブリックドメインの参考実装の出現は、その採用を助ける。 電子メールのために、設計に意見を言いたい人は誰でも発言権を持つ。した がって、アイディアの採用を助けるグループ精神があるが、最初は、その普通 の人は設計プロセスの一部であり、エキスパートのオブザーバー、あるいはエ キスパートのグループではないからである。単に、彼または彼女の名前をメー リングリストへ加えるように頼むだけで、ARPANETアクセスを持つ全ての人が そのプロセスに加わることができる。しかし、Quinquevirateは、定義の最終 ドラフトを見張るために、最後(1983年)にはエキスパートグループとして現れ るのだが。 いくつかのグループは、Common Lispがやってくることのパワーを理解して いない。Interlispグループは鍛え続けており、当然のことだが、それは、彼 らの受容グループはSymbolics/LMI受容グループと重なるからである。 Interlispに対する問題は、間違ったマシン - 遅いDマシンと人気のないVax - を持っていることである。InterlispのVax実装は、決して真に離陸することは なかったが、それは、ある程度は、完成していなかったためだが、大部分は、 Interlispの処理性能が受け入れ難いものだからである。もちろん、その問題 はInterlispによりもVaxに存在する: Vaxは、1つあるいは2つの大きなプログ ラムではなく、多くの小さなプログラムを実行するように設計されたので、ペ ージテーブルがページ化される必要があるために、ページサイズは2レベルの ページテーブルを必要とする。 当時、ARPAのLisp事業を監督していたARPAプログラムディレクタはRon Ohlanderであり、彼は、パワフルなCommon Lispの友人である。彼の友情は、 ある部分は、Lispの運命はAIの運命にとって中心的であるという彼の認識のた め、ある部分は、AIの参加者たちが、その下にあるテクノロジーに注意を払う 必要があると言うため、そしてある部分は、Common Lisp Groupが、彼と彼の 関心に多大な注意を払うためである。争い好きのLispコミュニティが、最終的 にはその行動を共にし、標準に同意するという考えがOhlanderの腕時計にある としておそらく間違いではないだろう。 2.11 他の普通のハードウェア方言: 1980-1984 Common Lispが開発されていた間、残りの世界がそのままだったわけではない。 Common Lispが多くの注意の焦点だったにしても。Portable Standard Lispは、 Vax, DEC-20, 種々のMC68000マシン, そしてCray 1に広がる。そのEmode環境 (後のNmode)は、成長するCommon Lispの面前でそれを"製品化した" Hewlett-Packardへアピールすることを証明した。 Franz Lispは多くのシステムへ移植され、1985年から1986年にCommon Lisp が一般に利用可能になるまでの数年間、普通のハードウェアの馬車馬になった。 Interlispは、1980年初めの間、その純粋な受容グループからの受容を獲得 した。PDP-10, Dolphins, Dorados, そしてVax上で動作し、Dolphinのような 価格でDoradoのような処理性能を持つと噂された、Dandelionと呼ばれる低コ ストのLispマシン上に現れそうだと思われた。 市場では、Dolphinは、その処理性能のステークス競馬(賭け金を一人または 数人で独占する仕組みの競馬)の点で叩かれていたが、それは主に、Interlisp 仮想マシンを実行するには遅いマシンだったからだ。Xeroxの努力は、移植と 処理性能に狙いを定めており、方言や環境の改善の領域でも仕事は続いていた が、これらにはあまり注意を払わなかった。主要なInterlisp開発者たちは同 調していた。 Interlisp/Vaxは姿をみせたが、3つの原因により失敗とみなされなければな らない: (1) Interlisp-Dよりも、PDP-10の最終的な逝去によって運命づけら れるInterlisp族の支流であるInterlisp-10との互換性を提供した; (2) ストッ プアンドコピーのガーベジコレクタだけを提供したが、それはVax上では特に 処理性能が悪い; そして、(3) Lisp世界の残りは、Interlisp界も含めて、パ ーソナルLispマシンに群がっていたので、Vaxは、少数のビジネスを除いては、 Lisp用としては真剣に考えられることは決してなかった。 フランスでは、Jerome Chaillouxと同僚たちが、Le_Lispと呼ばれる新たな Lispの方言を開発した。その方言はMacLispを思い出させるようなもので、移 植性と効率性に焦点をあてた。ヨーロッパのコンピュータ状況は、Lispに対す る合衆国の状況と同様には明白ではなかったので、それは移植可能である必要 があった。合衆国では、LispマシンがLispに対して支配的だったが、これらの マシンは、ヨーロッパでは同様に利用可能ではなく、しばしば法外に高価だっ た。ヨーロッパの研究所は、(合衆国の視点からは)ある範囲の風変わりなマシ ンをしばしば与えられたり獲得したりする。したがって、互換性は必須であっ た。 Vlispの経験は、処理性能と移植性が共存できることをChaillouxに教え、 Vlispのテクニックのいくつかを拡張して、彼のグループはゴールを達成でき た。1984年までに、彼らの方言は、約10の異なるマシン上で動作し、最も同等 の代替物であるFranz Lispよりもずっと良い処理性能を実証した。Vax 780上 で、Le_LispはSymbolics 3600とほぼ同等の処理性能だった。 加えて、Le_Lispは、Ceyxと呼ばれる一人前のプログラミング環境を提供し た。Ceyxはデバッギングの助けとなるものの集合、フルスクリーンでマルチウィ ンドウの構造エディタとプリティプリンタ、そしてこれもCeyxと呼ばれるオブ ジェクト指向プログラミング拡張を持っていた。 重要なのは、このLispのサブセットが、フランス教育省によって、教育を目 的としてフランスの高等学校へ供給され、Le_Lispユーザの一世代を供給した ことである。 Le_Lispは極めて移植性が高く、いくつかの移植は、数人で1週間の努力だけ しか必要としなかった。その言語は、その中でVlispインタプリタが書かれた 仮想マシンに哲学的に類似の仮想マシンに基づいており、コンパイラは、LLM3 と呼ばれるこのマシンに対するコードを生成した。マシン独立の最適化に加え て、ロード時の覗き穴オブティマイザが使われた。 Le_Lispは、この期間、Common Lispの歴史に現れようとはしなかったが、 1980年代の終わり、標準化戦争の間に目立ってきた。 Schemeコミュニティは、少数の熱狂的なファンから、プログラミング言語の 数学的側面への興味によって特徴づけられる、より大きなグループへ成長した。 Schemeの小さなサイズ、ラムダ算法の中にあるルーツ、そして一般的にコンパ クトな意味論の土台は、研究や教育のための媒体としてSchemeを人気のあるも のにし始めていた。特に、強力なSchemeサポーターのグループが、MIT, Rice, そしてインディアナ大学で発達した。一般に、これらのグループは、それらの 学校の教職員に加わったMIT卒業生たちによって始められた。 Schemeは、ConniverとActorをそのルーツとする結果として、継続を持った が、その概念は、あらゆる時点での継続を捕らえるための手段を提供する、プ リミティブCALL-WITH-CURRENT-CONTINUATIONの中でいくらか一般化された。こ のプリミティブを用いると、エンジン上でのインディアナ大学の仕事によって 例示されたように(??? Haynesを参照)、マルチタスキングの代替モデルのよう な物事を探求することが可能だった。 MITでは、Gerry SussmanとHal Abelsonの指導の元で、Schemeは、学部学生 の教育用に採用された。その本、計算機プログラムの構造と解釈[?]は古典と なり、より広いコミュニティでSchemeの悪名を躍進させた。商用のScheme の 実装を作るいくつかの企業が発生した: Cadence Research SystemsによるChez SchemeはR. Kent Dybvigによって、Semantic MicrosystemsはWill Clinger, Anne Hartheimer, そしてJohn Ulrichによって始められ、Texas Instruments はSchemeの1バージョンを出した。Chez Schemeはさまざまなワークステーショ ン上で動作し、Semantic MicrosystemsのSchemeはMacSchemeと呼ばれ、 Macintosh上で動作した。PC Schemeは、TIが作って販売したものと同様に、 IBM PCとそのクローン上で動作した。 オリジナルの改訂Scheme報告書(Revised Report on Scheme)は、Schemeの将 来の定義に対する1つのモデルとされ、自選のいわゆる"著者たち"のグループ は、Schemeを進化させる役割を持った。彼らが採用したルールは、全員の同意 の元でのみ、機能は加えられ得るということだった。 CALL-WITH-CURRENT-CONTINUATIONのような、ある種の機能が加えられてからか なり短い期間の後、Schemeの変更の速度は、このルールのために遅くなった。 高度に知的なグループでの同僚の圧力だけが、反対投票を変えることを強情な 著者に納得させることができた。その結果、ある機能がSchemeへ加えられると きはいつでも、それは明らかに正しいことであるという信仰が広く持たれてい る。たとえば、ようやく1991年の終わりになって、マクロが付録として - 部 分的に標準化された機構として - その言語へ加えられた。 "改訂, . . . , 改訂Scheme報告書"と呼ばれる、一連の改訂報告があった。 1991年の終わりに、"改訂改訂改訂改訂Scheme報告書"が書かれ、承認された; それは、愛情を込めて"R4RS"と呼ばれている。 後でCommon Lisp Groupのメンバーになった人の多くは、Schemeへの根強い 愛情と、そのような何かが次のLisp標準になることを見たいという、それほど 秘密ではない欲望を宣言したものだった。しかし、SchemeとCommon Lispコミュ ニティは、その10年の後半に、しばしば激しいライバルになるだろう。 2.11.1 Zetalisp Common Lispが始まった時期(1981年)、MIT Lisp-machine Lispはかなり進化し ていた。Common Lisp Group(前を参照)は、Zetalispの増大する影響を扱う必 要があった。 名前"Zetalisp"は、"Lisp上の最後の言葉"から採られた(???)。 Zetalispは、Symbolics版のLisp-machine Lispの名前だった。3600 - 前に 説明したSymbolicsの第2世代のLispマシン - はほとんど完全にLispでプログ ラムされたので、Zetalispは、この時点までのどの単一のLispの中にも見られ ない、かなりの能力の集合を必要とするようになった。Zetalispは、通常のプ ログラミングのためにだけ使われたのではなく、オペレーティングシステム、 エディタ、コンパイラ、ネットワークサーバ、ガーベジコレクタ、そしてウィ ンドウシステムは全てZetalispの中でプログラムされ、以前のLisp-machine Lispは、これらの仕事ができるほど優れてはいなかったので、Zetalispはそれ らを扱うために拡張された。 Lisp-machine Lispへの主な追加は、いわゆる非階層的オブジェクト指向言 語であるFlavorsだった。Flavorsについては、この節の中でもっと多くを語る つもりだが(???)、今のところは、Howard Cannonのいくつかのアイディアから 開発された、多重継承のメッセージパッシングシステムとだけ言っておこう。 そのアイディアを一貫したシステムへ発展したのは、大部分はDavid A. Moon によるものだったが、Cannonもキーとなる人物の一人だった。 Flavorsの機能は、Lispマシンのウィンドウシステムの必要性によって駆動 されたが、それは、長い間、そのプログラミングが多重継承を必要とする唯一 のシステムの例だとみなされていた。 その他の注目すべき追加はFORMATとSETF、複雑な配列、そして随意引数とキ ーワード引数のための複雑なラムダリストだった。FORMATは、基本的には、場 所取りを持つ事前に決められた文字列を取り、それらの場所取りに対して計算 された値や文字列を置換することで、文字列出力を便利に作り出すためのメカ ニズムである - それは、これよりもずっと複雑になったが、その場所取りは、 結果のリストを生み出すための繰り返しプリミティブ、複数形、そして他のそ のような風変わりなものを含んでいたためである。SETFは前で議論された。 Zetalispの受容と重要性における要因の1つは、Lispマシンの受容であり、 それは次の節で議論される。Lispマシン - とりわけSymbolics Lispマシン - は、商用セッティングでの真のLispの仕事に対する最も人気のある媒体だった ので、Lisp-machine Lisp (Zetalisp)がLispの主要な方言であるという明確な 信仰 - Symbolics自身によって助長された - が大きくなっていた。したがっ て、Symbolicsの人々は、より広いLisp標準の成功のための強力な政治力や必 須の政治同盟として、たいへん重要とみなされた。 2.11.2 初期のLispマシン企業 主なLispマシン企業は5つあった: Symbolics; Lisp Machine, Inc. (LMI); そ の第一の製品の後にPERQと改名されたThree Rivers Computer; Xerox; そして Texas Instruments (TI)である。 これらの中で、Symbolics, LMI, そしてTIはみな、彼らの売り物の基礎とし て、MITからライセンスされた基本的には同じソフトウェアを用いた。そのソ フトウェアは、Lispの実装、オペレーティングシステム、エディタ、ウィンド ウシステム、ネットワークソフトウェア、そして全てのユーティリティを含ん でいた。改善がMITへ渡し戻される限り、そのソフトウェアは安く(あるいは無 料で)利用可能であるという協定があった。 したがって、それらの企業は、第一にハードウェアの処理性能に基づいて、 しかし第二に、ソフトウェアが共通のソースへ渡し戻される前に、共通ソフト ウェアベースの中の前進が利用できることで競争した。いくつかの企業は、 SymbolicsのCやFORTRAN実装のような、専売の拡張も生み出した。 Xeroxは、Interlisp-Dを実行するD-machinesを生産した。 Three Riversは、Pascalに基づくオペレーティングシステムと言語、あるい は、後にCommon Lispの基になるSpice Lispのどちらかを実行するマシンPERQ を販売した。 したがって、全てのLispマシン企業は、既存のソフトウェアを用いて始まり、 全てのMacLisp由来のLispマシン企業は、大学からソフトウェアをライセンス していた。 これらの企業の中では、Symbolicsが最も成功し(前Common Lisp紀の終わり にインストールされているマシンの数で測ると)、XeroxとTIが続いているが、 おそらくTIは、1つまたは2つの大きな企業の購入に基づくと、最も多くインス トールされたマシンであると主張できるかもしれない。 Common Lispの方向性への非常に大きな影響のため、Symbolicsは、これらの 企業の中で最も興味深い - しかし、他の企業が強力な重要性を持たなかった とは主張したくない。Zetalispの人気 - あるいは、少なくとも、Common Lisp グループの他の人々への明白な影響 - は、大部分は3600の人気から生じた。 3600は第2世代のLispマシンであり、第1世代は、LM-2と呼ばれたCADRの1バ ージョンだった。SymbolicsとLMIは、どちらも、本質的にはCADRを生産するこ とでビジネスを始めた; LMI版はLAMBDAと呼ばれた。しかし、Symbolicsのビジ ネスプランは、もっとずっと速いLispマシンを生み出して、ワークステーショ ンのステークス競馬(賭け金を独占する競馬)に入ることだった。 しばしば忘れやすいのだが、1980年代初め、ワークステーションは風変わり で、一般に、多くの人が重要だと考えないほど計算的にパワー不足だった。 PDP-10は、未だにワークステーションよりもずっと良い処理性能を提供したし、 エンジニアがワークステーションに熱中してくるだろう、あるいは、ワークス テーションが大きな新しい市場を形成するだろうということは全く明らかでは なかった。さらに、Unixベース/Cベースのワークステーションが必然的に勝者 になることも明らかではなかったが、それは、ソフトウェア開発よりもアプリ ケーションが、市場を駆動するだろうと考えられていたからである。したがっ て、Symbolicsが、事実持ったそのビジネスプランを持つことは馬鹿げたこと ではなかった。 SymbolicsとLMIは、MIT AI Labでのライバルによって設立された。Richard GreenblattはLMIを、他のほとんど全ての人、とりわけMoon, Weinreb, Cannon, そしてKnightはSymbolicsを設立した。 Symbolics LispマシンとZetalispを採用した要因の1つは、最初の3600はガ ーベジコレクタを持たなかったことであり、それは、大きなアドレス空間をゴ ミ集めする処理性能上のペナルティが観測されなかったことを意味する。もと もと、3600はBakerスタイルのインクリメンタルなストップアンドコピーコレ クタを持つことになっていたが、アドレス空間がとても大きかったので、通常 のプログラムは、数日間はメモリを使い果たさず、激しいプログラムは8時間 程度の間は動作することができた。実行中のイメージをセーブするための機構 があったが、それは、基本的には、ディスクへのストップアンドコピーのゴミ 集めを行なった。したがって、実行中にゴミ集めする代わりに、プログラマは、 メモリが使い果たされるまで実行し、それから、ディスクへのセーブの長い (数時間に及ぶ)プロセスを開始し、夕食後あるいは次の日にプログラムを再開 したものだった。 インクリメンタルなガーベジコレクタは、最初の3600の数年後にリリースさ れ、ことによるとページングの問題のために、相対的に悪い処理性能を持つこ とがわかった。代わりに、Moonは、Smalltalkのために開発されたUngarジェネ レーションスキャベンジャコレクタに似ている、即時ガーベジコレクタを開発 した。ジェネレーションスキャベンジングを用いると、オブジェクトは、ストッ プアンドコピープロセスによって、ある世代から次の世代へ昇格させられる。 数世代の後、オブジェクトは、長期の記憶域へ昇格(終身在職) させられる。 そのアイディアは、あるオブジェクトは、その作成の後にすぐゴミになるので、 オブジェクトの年齢を見て若いオブジェクトだけに集中すれば、多くのゴミを 得られるし、小さなワーキングセットが維持されるので、ページングの性能が 良いというものである。 即時ゴミ集め[Moon, 1984]はそれと似ているが、世代を表わす若干のコンス 領域と、コンスする領域の中のオブジェクトへのポインタが作られるメモリ領 域のリストを維持し、それらの領域は、ある世代から別の世代へ移動しながら、 ストップアンドコピー操作の中でスキャンされる。Smalltalkでのオブジェク トは、Lispでほど頻繁には作られないので、そのトレードオフは少し異なり、 データ構造が異なる。 その即時ガーベジコレクタは効果的だとわかり、最初の3600が販売されてか ら数年後、効果的なガーベジコレクタが使用可能になった。ユーザが処理性能 の違いになれるのにはしばらくかかったが、そのときまでに、3600は、すでに 勢いのある受容グループをうちたてており、3600の地位は強固に植えつけられ ていた。 PERQは、文書準備コンピュータとして使われた、不十分な処理性能のマイク ロコード化されたマシンで市場に参入した。Scott Fahlmanは、この企業に関 係しており、Common Lispがデビューしたとき、そのSpice Lispコードは Common Lispにほぼ追従していたので、PERQは、Lispマシン上で最初にCommon Lispを利用可能なものだった。 オリジナルのPERQとその後継バージョンは、ピッツバーグ地区の外では、大 きな商業的なインパクトを与えることは決してなかったが、おそらく、その処 理性能や、価格対処理性能が相対的に不十分だったからだろう。 我々は、Xerox Dマシンの初期の歴史をすでに見た。Common Lisp時代の前、 それらの使用は、以前のInterlisp-10サークルの中に広く行き渡っていた。 Texas Instrumentsは、1984年の初め、ちょうどCLtL1が発行される前にLisp マシンビジネスに参入し始めた。彼らはVikingプロジェクトを始めたが、それ はSpice LispとMC68020で動作していた。後に、彼らは、純粋なLispマシンの 道を行くことを決定し、同じくMITソフトウェアを実行するマイクロコード化 されたマシンであるExplorerを導入した。後に、TIは、いくらかの技術を交換 するためにLMIに加わったが、それは、LMIに資本を注入して、その存在を延長 したことを除けば、どちらの企業のビジネスの成功にもほとんど、あるいは全 く影響がなかったように見えた。Explorerは良い価格対性能、そしてかなりの 処理性能も持ち、TIが国防総省によって持たれていた非常な寵愛が、初期 Common Lisp時代の間にTIに素晴らしい販売をもたらした。 2.11.3 衰えるMacLisp まだ広く使われており、そして多少は広がり続けていたが、MacLispの開発は、 1980年代の初めの間に停止した。この時点で、MacLispは、ITS, Multics, Tenex, TOPS-10, TOPS-20, そしてWAITS上で動作した。PDP-10、あるいは関連 マシン上でのみ利用可能ではあったが、これらはPDP-10, DEC-10, DEC-20, そ してFoonly F2とF4を含んでいた。 MacLispに対する資金は、Macsyma Groupによって提供されていたが、それは、 MITの視点からは、MacLispに対する主要なクライアントは、Macsymaを使って いる人々 - Macsyma Consortiumだからである。しかし、世界の残りの視点か らは、MacsymaはLispの興味深いアプリケーションであるが、MacLispは、AI、 とりわけ視覚とロボット工学のための研究と開発ツールとして、より広いアピ ールがあった。しかし、これらのグループは資金をたくさん持っているわけで はなく、いずれにせよ、自由に利用可能なMacLispの使用を受け入れることの 他にすべきなんらかの理由を見つけた人はいなかった。 MacLispに対する資金は、エネルギー省によるVax上のNILのための資金によっ て取って代わられた。エネルギー省は、民間のエネルギーのような、より良性 のプロジェクトに加えて、核兵器の研究と開発のようなことを監督していた。 したがって、DOEが代わりの国防予算の源であり、S1 Lispのようなプロジェク トに出資していた。 一般に、MacLispを用いる各サイトには、ことによってはJon L Whiteに相談 することで、遭遇する問題の多くを扱うことができる地元のウィザードがいた。 少なくとも1つの場合に、資金が、ある注文仕事をするために、MITに利用可能 になった。たとえば、WAITS上のMacLispの単一セグメント版は、Stanford AI Labによって支払われ、その仕事は、Howard Cannonによってオンサイトで行な われた。 MacLispは、何年にも渡って、種々の言語開発と機能に対するホストであり、 それらには、MicroPlanner, Conniver, Scheme, Flavors, Frames, Extends, Qlisp, そして種々の視覚処理機能が含まれていた。MacLispでの最後の主要な 研究の断片は、スタンフォードでのMartin E. FrostとGabrielによるマルチプ ログラムプログラミング環境だった[?]。この環境は、MacLispと、オペレーティ ングシステムのサポートを持つスタンフォードの画面エディタEが、メールボッ クススタイルのオペレーティングシステムメカニズム上で通信できるようにす るプロトコルを定義した。このメカニズムを用いると、編集に専念するコード は、下にあるホストコンピュータのタイムシェアリングメカニズムを使うこと で、Eを使っている全てのユーザ(非Lispのタスクに対してすら)に共有された。 しばしば、編集の目的で実行されるコードはオペレーティングシステムの中で 実行され、スワップインあるいはページインのためのコードを必要としなかっ た。Lispプログラムがエディタを制御することも可能だったので、Lispで書か れた非常にパワフルな"マクロ"を、難解なEマクロ言語の代わりに使うことが できた。この環境は、類似のLisp/Emacs環境を何年か先取りしていた。 しかし、Common Lispグループの最初の頃、DOEやMacsyma Consortiumによる VaxのためのNILに対する資金は停止されたが、おそらく、Lispマシンが Macsymaを良く実行するだろうという信念、Common Lispの開発がMacsymaに対 する共通基盤を提供するだろうという信念によって煽られたのであろう。 DOEの資金が停止したのとほぼ同じ頃、Symbolicsは、Macsyma Groupへ、 Lispマシンに基づくMacsymaを売り始めた。このグループは、1980年代終わり あるいは1990年代初めの解散まで、利益を出し続けた。 NILの資金の停止と共に、Jon L Whiteは、Interlisp上で働くためにXeroxに 加わった - 不思議な状況は想像することが難しい。まず、Whiteは、明らかに、 カリフォルニアのライフスタイルの全体的な雰囲気は彼が受け入れるにはあま りに異質に思えるような、はっきりした東部人の性格であった。第2に、何年 にもわたるMacLispとInterlisp間の競争は、彼らが一緒に働くことを防止して いるように見えるからである。 2.12 標準の発展: 1984-1990 Common Lisp: The Language (CLtL1)の発表の直後の時期は、空前のLisp人気 の時代の始まりを示した。この人気の大きな部分はAIの人気と結び付いていた が、完全にそうだというわけではなかった。その構成要素を見てみよう: 初め に、不備はあるものだったが、一般に同意されたLispのための標準があった; AIは日の出の勢いで、LispはAIの言語だった; 突然ワークステーションの市場 が出現したように見え、そのワークステーション上のLispの処理性能は、Lisp マシンから遠く隔たっているわけではなかった; ベンチャー資本コミュニティ はSunのような企業の成功を見て、AIの前途に畏怖の念を起こし、レーガン大 統領の任期の第1半期の俄景気の結果として多くの金を持っていた; コンピュ ータ科学者は、群をなして企業家に転身し、SunやValidのような同僚の企業の ほとんど即時の成功によって拍車がかかった。Lispに関する記事が人気のある 雑誌のために書かれ、Common Lispに対する要求が、CMU(Fahlman)やスタンフォ ード(Gabriel)のような場所へ流れ込み、さもなければ、アカデミックなだけ の人々が、AIやLispの話題についての産業会議やワークショップで話をするよ うに頼まれ、将来の動向の賢人とみなされた。 産業界によるLispやAIへの興味の背後にあるキーとなる勢いは、ハードウェ アの問題は制御下に入ったように見え、荒れ狂うソフトウェアの猛獣が次なる 飼い慣らされるべきものだということだった。より伝統的な方法は不十分に見 え、新たな、革新的なことが、古く、保守的なことよりも完全な効果を持つだ ろうという感じ - これは、単に印の魅力なのだが - が常にあり、ビジネスマ ンとベンチャー投資家の両者を引き付けた。 2.12.1 Lisp企業の概観 1984年 - CLtL1が出版された年 - と同じくらい早い頃、いくつかの企業が、 Common Lispを営利化するために設立された。これらは、Franz, Inc, Gold Hill, そしてLucid, Incを含んでいた。Lispの房上の他の企業は、Common Lispで、あるいはCommon Lispへ至る道中にあるLispで、Lispの楽隊車に加わっ た。これらは、Three Rivers (PERQ)やTIを含んでいた。いくつかの主流のコ ンピュータ製造業者が、Lispビジネスに加わった。これらは、DEC, HP, Sun, Apollo, Prime, そしてIBMを含んでいた。SiemensやHoneywell Bullのように、 いくつかのヨーロッパの企業がCommon Lisp楽隊車に加わった。そして、古い 競技者がCommon Lispの仕事を始めた。これらは、Lispマシン企業とXeroxを含 んでいた。日本からの新たな競技者 - Kyoto Common Lisp (KCL) - は、ちょっ としたスポイラー((有力な候補の当選を脅かす)自分自身は当選の見込みのな い候補者)を提供した: KCLは、Cへコンパイルするコンパイラを持ち、それはC コンパイラによってコンパイルされる。このLispは本質的にフリーにライセン スされ、Common Lisp企業は、突然驚くべき競争相手を持ったのだった。 フリーの、質の高い製品は、高価で、より質の高い製品を容易に打ち負かす だろうと考える人がいるかもしれないが、これは正しくないと証明されており、 その無料の競争相手にもかかわらず、Common Lisp企業は繁栄した。よりよい 処理性能、よりよい品質、標準と共に前進するという開発者による約束、そし て、よりよいサービスが、値札がないことよりも重要であることがわかった。 2.12.2 Common Lisp企業 Franz, Inc.,は、Vaxsymaと呼ばれるMacsymaの1バージョンを移植するために 使われた、MacLispに似ているLisp方言であるFranz Lispを販売するビジネス をすでに行なっていた。Franz Lispは、それらしいCommon Lispが現れるまで、 Vax上での最も人気のあるLispの方言だった。Franzは、Common Lisp市場に参 入することを決定し、そのFranz Lispの販売からの収益でその努力に資金を供 給している。Franzの主要な設立者は、Fritz Kunze, John Foderaro, そして Richard Fatemanである。Kunzeは、カリフォルニア大学バークレイ校の数学科 で、Fatemanの博士課程の学生だった。Kunzeは、Franzを始めるために大学を 離れたのだが、難しい時期にプログラマを結集できる、そして、80年代の終わ りにLispビジネスが衰えていく時でももちこたえることができる、環境適応力 のあるビジネスマンであることがわかる。Foderaroも、バークレイからの数学 博士号を持つ、Fatemanの以前の学生である。彼は、Franz, Inc.によって提供 されるさまざまなLispの主要な設計者かつ実装者である。彼は、人前では物静 かで思慮に富んだ人物であり、進行中のCommon Lispの仕事へ重要な貢献を容 易になし得る能力があるにもかかわらず、人前で内気であることが彼が支配的 な役目を演じることをさせずにいる。Fatemanは、MITでの元々のMacsymaの実 装者の一人であるが、MacLisp/Lispの松明をバークレイへ運び、そして、 MacsymaをVaxへ移植することに責任を有していた。Macsymaは、ある程度DOEの 資金の元で開発されたのだが、MITの資産なのか、公有なのかについて論争が あった。Fatemanは公有だと主張し、Macsymaをサポートするのに適している LispをVax上に載せるためにグループを呼び集めた - これがFranz Lispだった。 MITは、彼の行動に腹を立てた。 Franzは直販戦略を採用し、顧客に目標を定めて、彼らへ直接販売した。 Gold Hillは、Carl Hewittと彼の学生Jerry Barberによって設立された Apiary, Inc.と呼ばれる親会社の一部門である。Apiary/Gold Hillを設立する 前に、Barberはその年をフランスのINRIAで過ごし、そこで彼は、IBM PCのた めのMacLisp/Zetalispに似ているLispを書いた。この仕事は、一部はINRIAに よって資金を供給された。彼が戻ってきたとき、彼の方言は、HewittとBarber が、すぐにCommon LispになろうとしているLispとしてその存在するLispを売 ることによって、Common Lispへの関心の波を利用できると考えたほど、 Common Lispに十分に近いものだった。PCはAIにとって重要なマシンになると 信じられていたので、それは鉄壁のビジネスプランであるように思われ、種々 の魅力的な東海岸のベンチャー投資家たちが投資した。Gold HillのLispは Common Lispではなく、そして最初の年月には、その企業は、偽りの広告に対 するいくらかの批判に耐えていたが、そのLispがCommon Lispへ変形されてい くにつれ、その質は明らかに落ちていった。同じ頃に"AIの冬"が直撃し、Gold Hillは、かつてのレベルへ蘇ることはできなかった。ベンチャー投資家から捨 てられ、全ての従業員を単に解雇し、今日は2人で操業を続けている。 "AIの冬"は、AIの不幸な商用化の運命を記述するために、1988年に初めて使 われた語である。1970年代後半から1980年代中頃まで、人工知能はコンピュー タビジネスの重要な部分だった - 多くの企業が、ハイテク操業開始に対して 当時は豊富だったベンチャー資本で開始された。1988年までに、ビジネスアナ リストたちにとって、AIは華々しい成長を経験しないだろうということが明ら かになってきて、商業的な関心としてのAI、そして、それと共にLispに対する 急激な反動があった。AI企業は、実際の財政危機に直面し始め、Lisp企業もそ うであった。 元々のGold Hill Lispは、動的スコープを持つ、Lisp-machine-Lispに似て いるLispだった。Common Lispへの移行は何年もかかった。Common Lispへの移 行の期間、Gold Hillは多角化を試み、エキスパートシステムシェルを組み立 てた。このシェルは、AIの冬が直撃したのとほぼ同時期にリリースされたので、 期待されたほど会社を救うには至らなかった。 Gold Hillも、同様に直接販売を行なった。 Lucid, Inc.は、Gabriel (Stanford), Rod Brooks (MIT), Eric Benson (Utah/PSL), Scott Fahlman (CMU), そしてその他数人によって設立された。 ベンチャー資本に背を向けて、Lucidは、他のCommon Lisp企業とは異なる戦略 を採用した。第1に、ゼロからCommon Lispの実装を書き、そして第2に、OEM戦 略を採用した。OEMルートのアイディアは、市場へのコンピュータ(ハードウェ ア)企業と取り決めを行ない、その名前でLispを売ることである。しかし、そ のLispは外部の企業、この場合はLucidによって実装および保守され、Lucidは ロイヤルティをとるだろう。すぐに、Lucidは、Sun, Apollo, そしてPrimeと のOEM取引を確定した。これが可能だった理由は、Lucidはその設立者たちの名 前の強力さと、ゼロからCommon Lispを書いていて、したがって、最初の真の Common Lispになるだろうという事実を利用したためである。 Sunの創設者の何人かはスタンフォード出身であり、Gabrielと、Common Lispの定義における彼の役割を知っていたので、Sunは一部分にサインした。 最終的に、LucidはそのLispを移植し、IBM, DEC, そしてHPとOEM契約を結ん だ。ロイヤルティは、比較的に、コピー当たり小さなものだったが、そのOEM ルートは、第1の普通のハードウェアのLisp企業としてLucidを確立した。ハー ドウェア企業はAIとLispに対するビジネスの機会に関して熱狂的だったので、 そのビジネスに多くを投資した。彼らはしばしば、ロイヤルティと同様に、大 きな移植料、決まった値段のライセンス料、メインテナンス料を支払ったもの だった。OEMとしてSunを獲得したことは、Lucidの生き残りにとってキーとな ることだった。なぜなら、Sunワークステーションは、そのLispへ顧客を引き 付けるのに必要な印を発展させていたからだ。Sunは、常に先端だと考えられ ており、先端のAIテクノロジーに興味がある人々は、まずSunへ進んだ。また、 Sunは、自身でLisp開発を行なったエンジニアの多くを、ほとんどはプログラ ミング環境の領域に雇用した。 AIの冬が直撃する前に、Lucidは、他の言語(C/C++)とプログラミング環境に 多角化し始めた。80年代の後半、Lucidは、OEM企業から直販企業へと変化しよ うとし始めたが、それは、ある程度は、収益が以前のようには高くなく、確か に以前ほど歳入の高い割合を占めなくなったとき、そのOEM企業は、Lispに開 発やマーケティングの金を費やすことにあまり興味がなかったためである。 2.12.3 他のLispマシン企業 Three Riversは2番目のLispマシンを作り、それは以前のモデルよりもよい処 理性能を持っていたが、それでもなお、3600や、より速いMC68020ベースの Common Lispと同じくらいよい処理性能では到底なかった。そのLispは、かな り完全なCommon Lispへと改良されたが、これは、決して成功した会社ではな かった。80年代の後半、それはビジネスを止めた。 TIは、不運なVikingプロジェクトの後、Lispマシン企業への転換を図ってい た。TIは、Patrick Dussud(後のCLOSの話の中に現れるだろう)を含む、2、3の よい人々を雇った。TIはLMIとビジネスの協定を結んでいたのだが、彼は、 SymbolicsのDave Moonと密接な仕事上の関係を発達させていた。この関係を通 じて、両方の企業は、そのLispソフトウェアの処理性能を改善することができ、 そのため、SymbolicsとTIは、80年代の第3四半期の主要なLispマシンベンダで あった。 LMIとの協定のために、TIは、Explorerが完成する前に、LMIのハードウェア 上に自身のマイクロコードを開発することができた。TIはLMIのソフトウェア を使う権利を持っていたが、MITのソフトウェアを代わりに使うことを選んだ。 LMIは、Explorerを再販売する権利を持っていたが、そうしないことを選んだ。 TIは、3つのモデル、Explorer I, Explorer II, そしてExplorer II+を作っ た。また、DARPAとの契約の元で、精巧なLispチップも作った。Explorer IIと II+は、どちらもこのチップを使った。TIは、Micro Explorerと呼ばれるボー ドレベルのLispマシンも作った。このマシンも、そのLispチップを用いた。 2.12.4 自身のLispを持つ大企業 DECとHPは、自身のLispを実装した。DECはSpice Lispのコードから、HPはPSL から始めた。それぞれの企業は、AIは離陸し、Lispを持っていることは、AIビ ジネスでの成功のための必須の構成要素だと信じていた。DECとHPは、どちら も、それらの上で働いていた学生を雇うことで、また、進行中のコンサルティ ングを準備することで、これらのLispの元の実装者たちと協定を結んでいた。 DECとHPは、どちらも、これらのLispグループからかなり大きな、他のLisp企 業の基準では大きな、ビジネスを育てた。1980年代の最終四半期のLispのピー クで、歳入によるLispビジネスの主要な競技者は、Symbolics, TI, DEC, HP, Sun, そしてLucidだった。 DECとHPは、彼らのLisp販売物に、主として環境の領域だったが、Lispシス テム自身の処理性能にも多くの努力をつぎこんだ。 1980年代の最終四半期、HPは、PSLは勝者ではなく、Common Lispを提供する 必要があることを理解した。彼らは、それを提供するためにLucidを選び、自 身のエンジニアリングスタッフを減らし、よりマーケティングに焦点をあてる ことを選んだ。その決定を下したとき、AIの冬がちょうど彼らの上にあったの で、この状況の認識が、彼らにLispの投資を削減させたのかどうかは明らかで はない。 1990年代初頭、AIの冬の最中に、DECも自身の努力を破棄して、同様にLucid を選んだ。 2.12.5 IBM IBMは、Lispに適している多くのプラットフォーム: PC, メインフレーム, そ してRTを持っていた。これらのうち、当初IBMは、RT上にだけCommon Lispを載 せることを決定した。IBMは、RT上にSpice Lisp (Common Lisp)を載せるため の試験的なプログラムに資金を供給したが、それは、ワークステーション市場 へのIBMの最初の真の参入になるものだった。Spice Lispの最高指導者である Fahlmanは、Lucidの創設者の一人でもあり、このコネのおかげで、Lucidがそ のLispをIBMのためにRTへ移植するという契約書が最終的には書かれた。その 移植が終わっていなければならないときには、RTは、自分のウィンドウシステ ムを持っていなかったが、後にはそれを持ち、そして、その契約は、Lucidが 完全な環境を納めることを要求した。その上に高レベルのLispウィンドウシス テムが書かれる低レベルのウィンドウシステムに加えて、多くの努力がこの環 境につぎこまれたが、RTは商業的には失敗作であり、それは主にとても貧弱な 処理性能のためだった。 後にIBMは、そのRS6000でワークステーション市場に再び参入したが、それ はよい処理性能を持っており、Lucidはそれに対するCommon Lispを作成した。 IBMは、結局は、370と、Unixの1バージョンであるAIXを走らせているPS-2の上 に同じLispを提供するためにLucidと契約した。IBMが、そのLispシステムのた めに、たった1つの企業と協業するのを選んだことは道理にかなっているよう に見えるかもしれないが、状況は、異なるビジネスユニットがここで述べられ たそれぞれのハードウェアファミリーに対して責任を持っており、これらの間 ではIBM内でもやりとりはなかった。従って、1つのビジネスユニットが、強制 ではなく1つの特定のベンダを選んだことは、興味深く妥当なことであった。 これらのプラットフォームのそれぞれに対する交渉は、まるで別の企業とのも ののようだった。 2.12.6 Xerox Xeroxは、Interlispの上にCommon Lisp互換パッケージを作成した。このパッ ケージは、Xeroxにとって、決して真の強力な成功ではなかった。Xeroxは、 1980年代の後半にLispビジネスから撤退し、1989年に、Envosと呼ばれるXerox から始まったスピンオフへ、そのLispソフトウェアをライセンスした。 Envosは、真のCommon Lisp実装を作りだし、Interlisp-D環境に、Notecards やRoomsのようないくつか他のXeroxソフトウェアを加えて販売した。Envosは Xeroxによって資金を供給されたが、設立されてから3年後にビジネスから撤退 した。Envosが残したものは企業Venueになり、本質的には、その同じソフトウェ アを販売し続ける権利を許されていたが、直接の資金の供給はなかった。その 資金は、サービスしているXeroxのLisp顧客ベース(メインテナンス)によって 供給された。 2.12.7 Kyoto Common Lisp 最後の主要な競技者は、Kyoto Common Lisp (KCL)である。このLispは、当時 学生だった湯淺と萩谷によって京都大学で開発された(???)。これらの学生は、 Common Lispコミュニティの一部でも、合衆国のLispコミュニティの一部でも なく、彼らの実装は、CLtL1を読んだことだけに基づいていた。彼らは、その 本の興味深い読み違えを幾つかしたが、その結果は、非常に忠実なCommon Lispだった。 さらに、彼らは、合衆国では使われない実装テクニックを使った: Lispコー ドをCコードへコンパイルし、そのCコードがCコンパイラへ渡されたのである。 KCLは、ゴミ集め, IOなどをサポートする実行時環境を提供したが、このLisp を新たなマシンへ移植するのは、そのマシンのためのCコンパイラがどれだけ K&R Cに忠実か、そして、オペレーティングシステムに依存するものがどれだ け移植が難しいかによって変わったが、わずか数日から数週間しかかからなかっ た。 KCLは、合衆国内にフリーでライセンスされ、ある合衆国のCommon Lisp企業 - カリフォルニアのIbuki - は、基本的には、それを再パッケージしてサポー トしたが、幾つかの新たな開発を提供した。 Lispが、そしてCommon Lispが、このように効果的に実装され得るとは、主 要な合衆国のLisp実装者の誰の心にも、決して真剣には浮かばなかった。低レ ベルのコード生成を行なうコンパイラは、元のLisp構造を利用可能ではなく、 単に自動的に生成されるCの文の列だけを持つだろうから、コンパイルはあま り良くはできないだろうと考えられた。さらに、コンパイル速度は、二重のコ ンパイルのために悪くなる必要があると考えられた。のろくはあるが、このコ ンパイルのモードは、Lucid, Franz, そしてその他によって作られた、概して のろいコンパイラよりもずっと悪いというわけではない。 だから、その実装テクニックは、重大な欠点を持っていないだけではなく、 移植時の利益は著しかった。それにもかかわらず、KCLは、1990年代初め、ゼ ロのコストが重要である主として大学で使われており、KCLが、CLtL2や、それ が現れた時にANSI Common Lispの言語レベルへ育て上げられるだろうチャンス はあまりない。 2.12.8 処理性能への執念 1981年、Larry MasinterとDick Gabrielは、Lispシステムの処理性能をどのよ うに評価するかの研究を始める。この練習は、ユーザが行ない始めていた、種々 の略式のベンチマークを扱うためになされた。どの実装が - そしておそらく どの方言が - より優れた処理性能を持つのかを見つけ出したいので、ユーザ は、そのようなベンチマークに興味を持っている。ときどき、ベンチマークを 行なう人は、ある方言が他よりも優れていることを証明したいと思う。しかし、 Lisp言語はとても複雑で、Lisp実装はとても入り組んでいるので、りんごとみ かんを比べることで終わりやすい。 中でも、Lispは、プリミティブと抽象の両方を一様な言語のレベルで扱う。 例えば、多くのLispマニュアルでは、SETQとAPPENDは同じような方法で記述さ れるので、SETQとAPPENDはどちらも単位時間、そして通常は単に1つのマシン 命令だけを要すると推測することはもっともなことである。しかし、APPENDは、 先頭から線形に走査することでリストの末尾を見つけることを伴う、複雑な操 作である。Lispの実装と表現に慣れていないユーザは、容易に混乱してしまう だろう。 さらに、実装者が行なうことができる種々のトレードオフがほとんど常にあ り、空間と時間、ある操作のカテゴリーの時間と別の時間、最悪の場合と平均 の場合と最良の場合の時間、などのトレードがある。 MasinterとGabrielは、彼らが考え得る限りの全ての要素を説明しようと試 み、1982 ACM Symposium on Lisp and Functional Programmingでこの論文を 発表した[Gabriel, 1982]。 この論文に基づいて、Gabrielは、ベンチマークが示すものの分析に加えて、 一連のベンチマークの定義と収集を行なうために、そして、できるだけ多くの 既存の実装を比較するために、ARPAの契約を獲得した。その仕事は1984年に完 成され、ついにその結果は、1冊の本として出版されることになった; いわゆ るGabrielベンチマーク[Gabriel, 1985]は、Jack Dongarraのスーパーコンピュ ータ処理性能のLINPACK測定[?]に社会的な機能において比較し得る、Lisp処理 性能の定義として出現したのである。 Common Lispや商用のLisp実装の出現とともに、ユーザの処理性能への執念 は、Gabrielベンチマークの中に便利なはけ口を見つけた - それらは、明らか に処理性能の客観的な測定を提供したので、見込み客は、Gabrielベンチマー クの結果を見せることを要求した。 トレードで示したように、幾つかの企業は、競争相手がそれらを利用するだ ろうという恐れのために、彼らのGabriel処理性能数値を示すことを拒んだ。 その状況は、GabrielがLisp企業を始めて、その企業が中心的なセールスの 武器として処理性能を用いた時に、より複雑かつ対立的になった。そして、 GabrielベンチマークはGabrielによって開発されたので、その戦術は非倫理的 だと考えるものもあった。Franzは、そのベンチマークを、扇動的な"Gabriel Benchmarks"の代わりに、"標準処理性能評価ベンチマーク(Stanford Performance Evaluation Benchmarks)"と呼んだ。 2.12.9 日本 この時期、日本はLispを使うことに気づき、幾つかの企業は、MITIによる明白 なPrologの推奨にもかかわらず、Lispの仕事を後援した。ある程度は、これは、 日本で定着し始めていたKyoto Common Lispによって拍車がかかった。またあ る程度は、修士学生として合衆国でLispを学んだ以前の学生たち、後に主要な 日本の大学で先任教授になったり、日本の企業で上級管理職になった人々によっ て拍車がかかった。 特に興味を持たれているものは、論理プログラミング、あるいは、オブジェ クト指向プログラミングにLispをさまざまに融合することである。この最良の 例はTao [Okuno, 1984]であり、3つの影響全てを融合するものであった。Elis と呼ばれるマシンが、LispやTaoを実行するために、NTT(Nippon Telephone & Telegraph)によって設計/製作された。このマシンが、日本や、どこか他のと ころで流行ることはなかった。 大きな日本のコンピュータ企業の多くは、ゼロから、あるいは、他のLispを 元にして、またはKCLのいずれかからCommon Lispを実装した。ISOグループが 始まるまでに、日本にはLispに興味がある幾つかの国家の標準化グループがあっ た。1つはJIS(Japanese Industrial Standard)であり、合衆国のANSIに相当す る。JISの言語委員会は、先任教授に支配されており、JIS Lisp委員会 - McCarthyの学生である伊藤貴康教授に率いられている - は、理論的な視点か らLispに興味があり、JEIDAのようにはCommon Lispを真剣には考えなかった。 JEIDAは、複数企業の緩やかな連合であり、ここでも一人の教授によって統 一されているが、この場合、教授は若いCLtL1の翻訳者である井田昌之である。 井田は、国立大学の1つで先任教授である伊藤と比べて、より小さく名声が高 くない大学の出身であるが、Lispと、それを使う人々の商業的な成功に関心が あるので、工業グループから重んじられた。他方、伊藤は、実際的な言語の使 用よりも、数学的な理論を構築するのに適するエレガントな意味論に関心があ る。後で、標準化の話の中で、この両者について更に見るだろう。 2.12.10 DARPAとSAILメーリングリスト CLtL1が1984年に出版された直後、ARPAはDARPA(国防総省高等研究計画局 (Defense Advanced Research Projects Agency))と改名された。この頃、 Steve Squiresは、NSAからDARPAに加わり、一種の熱狂と、考えられているほ どには最近では計画局ではあまり見られない、政治力の重要視をもたらした。 彼は、まるで巣の中央にいる蜘蛛のようであり、彼の指はあらゆる糸の引っ張 りを感じ、彼の方向を、それに触れた全ての人へ向けようとした。Common Lispは、正当にも、その10年間のDARPAの輝かしい成功の一つと呼ばれる得る ものであるから、薄弱な主張よりも事実に基づいて、なし得ることを素早く固 めた。すなわち、この時点までは、DARPAは目立たない役割しか演じていなかっ たが、彼は、DARPAの役割を増やすために、そして強みを押しつけようとする ために、行動を開始した。 最初の行動は、カリフォルニア州MontereyのNaval Post-graduate Schoolで、 ポストCLtLのコミュニティを組織したことだった。Post-graduate Schoolは、 DARPAが会議を開く通常の場所の一つだったが、一般的に地元に縛られた Common Lisp Groupにとってはいくぶんエキゾチックな場所だった。そして、 Common Lisp Groupには自然なリーダーがいたのだが、DARPAは、会議をまとめ るために、正式のリーダーの何人かを選んだ。その会議は、1984年終わりに開 かれた。 標準を、誰もが知っている領域へどのように最良に拡張するかとみなされた 主な疑問は、実際にLispの一部だったが、それは従来は標準化されなかった。 これらは、以下のものを含んでいた: マルチプログラミング、ウィンドウ、エ ラーハンドリング、オブジェクト指向プログラミング、サブセット、グラフィッ クス、外部関数呼び出し、繰り返し、イエローページ、ブルーページ、そして 環境。その会議の結果 - DARPAが何を企んでいるかに関するCommon Lisp Group間の混乱は除いて - は、メーリングリストの集合であり、それぞれ興味 のある領域に対して一つ存在した。Gabrielは、もともとのリストを管理して いたので - つまらない仕事を行なう人は、やがて勝ち犬になるという理論に より、これらのリストを自発的に維持した[?]。 次の年には、これらのリスト上にほとんど活動は見られなかったが、参加者 の多くを占めているLisp実装者たちは、Common Lispの実装に、あるいは、会 社をうまくやっていこうとするのに忙しいからである。 2.12.11 X3J13の開始 1年後の引き続いての会議の中で - 1985年マサチューセッツ州ボストンで、明 白に恵み深い技術的な会議は、衝撃的な発表によって中断された。3つの主な 課題であると考えられた技術的な議事日程は: オブジェクト指向プログラミン グ、ウィンドウ、そしてユーザの必要性だった。議事日程の一部であるオブジェ クト指向プログラミングは、CommonLoops、Object Lisp、HPオブジェクト指向 プログラミング(HPOOPS, 後にCommon Objectsと呼ばれる)、そしてNew Flavorsの発表によって支配された。議事日程のウィンドウの部分は、Lucidの RT起源のウィンドウシステムと、Intellicorpによって作られたウィンドウシ ステムであるCommon Windowsの発表だった。会議のユーザの関心の部分は、な ぜユーザ - AI企業 - はLisp以上のもの、とりわけオブジェクト指向プログラ ミングとウィンドウを必要とするのかに関する単なる議論だった。 突発事件は、Steve Squiresが、Common Lispに対するANSI標準化グループを 設立する必要について話すように、Bob Mathisを紹介したことだった。聞かれ たニュースはこのようなものだった: Lispに対するISO標準化グループを開始 する構想が進行中であり、合衆国が応答する唯一の方法は、ANSIの名の元の代 表を送るLisp標準化グループを持つことだった。そのグループが話されたこと には、ヨーロッパ人はCommon Lispを好まず、非Common Lispの標準を作りたい と望んでいるという、絶え間ない不平があった。この努力は、フランスとイギ リスによって率いられており、合衆国は、"フランス人ども"に召集の職を与え るようにすることでAPLを避けたいと望んでいた。 この失言はとりわけ損害を与えた。なぜなら、その部屋の後ろに座っていた のは、EuLispの努力のリーダーであるJerome Chaillouxだったからだ。彼と共 に座っていたのは、優れたフランスのオブジェクト指向プログラミングの人材 であるPierre Cointeと、その他の何人かのヨーロッパ人である。 Bob Mathisが、最初のISO批判をかわすことによって、その日を救うために DARPAによって送られた。彼はこれを、Lispが標準化に適しているかどうかを 決定するために、Mathisが率いるだろう調査グループを推薦することで行なっ た。このグループは、1年間で報告することになっていた。これは、合衆国に、 標準化委員会を開始してその戦略を練るための1年間を与えた。 Mathisは、ISO ADAワーキンググループに対する召集係だったので、プロセ スを通じて標準を世話する経験を持っている。彼は、駆け出しのCommon Lisp Groupを助けるようにSquiresに頼まれた。唖然として、グループはどのように 返答すべきかわからなかった。脅威の深刻さ - いや、脅威の存在 - に驚くこ との他は。それにもかかわらず、幌馬車隊は出発しており、この会議でなすべ きこととして残されているものは、実権を握っている不可思議なBob Mathisと 共に、X3J13になるだろうもののための最初の組織会議をスケジュールするこ とだけであるように見える。 申し分のない政治家であるMathisは、部隊を結成するのにFahlman, Steele, そしてGabrielの助けを得た。 DARPAは、ヨーロッパの努力を恐れる理由は、ある言語に対するISO標準があ る場合、合衆国は、国防に関係する仕事の中でそれを使わなければならないと いう法律があるからだと述べた。もちろん、例外とかそういったことを用いて、 この法律を迂回する方法はたくさんあるが、しかし、ことによると、グループ が話されたことには、これらのメカニズムが常にうまくいくわけではなく、お そらく、DARPAはこのようなCommon Lispに友好的なプログラムマネージャの集 合ばかりではないかもしれない。 選ばれた道は、X3の道であり、IEEEではなかった。X3は、コンピュータと情 報処理に関係しなければならない標準化会議の集合であり、全てはCBEMAと呼 ばれる組織の中にある。X3の下の委員会は、ANSIへ提案された標準を提出する 権限を与えられており、その標準は、その後、公的なレビューのプロセスを実 行し、標準として出版される。この手はずは、COBOLを使っていた幾つかの企 業が、改変するために多くが多量のコストを必要とするCOBOL標準を作ったこ とによってそれらの企業を危険にさらしたとして、個々の技術的な専門家を訴 えたように、企業による訴訟から技術的な専門家を守るためである。ANSIは、 彼らの努力に対して個人として訴えられ得る場合、標準化の仕事を行なう技術 的な専門家を見つけることは困難であろうことを恐れた。 [以下のテキストは非常に不完全であり、書き入れられる必要がある。] - 数ヶ月後、X3の活動を開始するために、DCのSPARCで会議がある。この会議 では、標準化のゴールが議論され、最大のトピックは、SquiresとScherlis の名でDARPAによって押しつけられたものだが、Schemeの活動と融合するか どうかである - 技術的な課題は、マクロと、1-Lispであることを取り巻い ている。また、新たな(X3J13になる)X3グループのゴールが議論された。 BobrowとGabrielは多くの話をしたが、この会議の特徴は、いくぶん思い出 すことが難しいものである。 - 愚かにも勇敢な努力により、Gabrielは、融合についてSchemeコミュニティ に接近しようとするが、彼らは、本当に速く後退する。Clingerは、そのア イディアに共感する数人のうちの一人だが、彼とGabrielの組み合わせでは 十分ではない。この頃、Schemeコミュニティは、SchemeはLispの方言である ことの否定と、よりAlgolへ近い絆の主張を始める。 - GabrielとPitmanは、ClingerやSussman/Abelsonの助力を得て、マクロと 1-lispに伴う技術的な課題を詳述するレポートを作成する。希望を提供する Kohlbeckerによる学位論文[Kohlbecker, 1986b]があり、その論文の中で幾 つかの代替案が考慮されている。この論文は、LASC [Gabriel, 1988]で発表 される。融合に対するアイディアは死ぬ。 - 1986年の夏、L&FPがMITで開かれる。この会議は、ヨーロッパのLispコミュ ニティと合衆国のLispコミュニティが喧嘩の身構えをする最初である。 EuLisp委員会は、階層化されたLispの定義に対する提案と共に、unCommon Lispの論文を提示する[Padget, 1986]。会議の施設の階下の部屋でミーティ ングがあり、そこで、どちらのグループも他方を信用していないことが明ら かになる。合衆国は、ISO委員会を始めることで、ヨーロッパ人たちが Common Lispを沈めようとするのではないかという恐れだけのために、X3J13 を始めたという見方を示し、ヨーロッパ人たちは、X3J13が彼らのLispの努 力を沈めることを止めるためにISO委員会を始めようとしていると主張する。 Mathisは、そのレベルで、ISOグループを撃退しようとしていたが、機が熟 そうとしている。 - 1986年11月に、GabrielはEuLispの会議に出席する。EuLispは、非常にはっ きりしたLe_Lispの後継者だが、オブジェクト指向機構、モジュールなどを 持つ、小さなものから大きなものまでの種々のマシン上で動作する、階層化 された言語を定義しようとするヨーロッパの努力である。大部分をCommon Lispと互換にすることが一つのゴールである。Chaillouxの姿勢は、Common Lispへの橋を掛けようとすることのように見える。彼は、幾つかのX3J13の 会議にオブザーバーとして出席し、妥協案をつくり出そうとGabrielと共に 働こうとしている。 - X3J13は、何個かの大きな提案を作るために、いくつかのワーキンググルー プを開始する。これらは: 繰り返し、コンパイル、編集、そしてオブジェク ト指向プログラミングである。DECのKathy Chapmanが編集長に任命される。 DECは、2年のあいだ編集者を提供するには悪い時期を選んだ。 - 4つのグループが、Common Lispのオブジェクト指向プログラミング部分の定 義において競争する: New Flavors (Symbolics) [Symbolics, 1985], CommonLoops (Xerox) [Bobrow, 1986], Object Lisp (LMI) [Drescher, 1987], そしてCommon Objects [Kempf, 1987]である。6ヶ月間の戦いの後、 以下のグループは、CommonLoopsと、New Flavorsに少し基づくCLOSのための 標準を書くように言われる: Moon (Symbolics), Bobrow (Xerox), Kiczales (Xerox), Sonya Keene (Symbolics, ライター), Linda DeMichiel (Lucid), そしてGabriel (Lucid)である。最後の二人は仕様を書くことになったが、 中立的な影響を表すためにグループにいる。また、非公式にそのグループに いる消息筋の人々のグループもある: Patrick Dussud (TI), Jim Kempf (Sun), そしてJon L White (Lucid)である。 - ISOは、ワークグループ(WG16)を始めるために投票を求め、X3J13は賛成を投 じる。政治的な操縦を通じて、フランスが召集係になり、合衆国が編集係に なる。X3J13では、Mathisが議長に、Steeleが副議長に、Gabrielが国際的な 代表として票決される。GabrielとClingerは、ISO Lispに対する合衆国の編 集者として指名される。最初の会議は、1987年2月にパリで開かれる。それ に先立ち、さまざまなLispの話題に関する小さなワークショップがある。合 衆国は大きな代表団を、その中の何人かは、私企業の少額の金で、送る。 DARPAは、Mathis, Gabriel, そしてClingerに対して支払う。また、そこに はMcCarthy - 合衆国の真剣さへの信用を与えるために, Masinter, Gregor Kiczales, そしてKent Pitmanもいる。合衆国は、合衆国のCommon Lispを危 険にさらすようなことが何も起こらないにようにせよという指示を与えられ る。丸一日が、その名前(ISLISP)とゴールに必要とされる。ゴールは、明快 性、簡潔性、一貫性、緊密性のようなものを含む(??? これらを議事録でチェッ クすること)。Common Lispから始めるが、多くのものを否決することが決定 される。これはフランスの提案である。合衆国は、この委員会は既存の物事 だけを標準化できると指摘する一方、ヨーロッパの人達は委員会の中で何か を設計して幸せそうである。Schemeはその基盤として拒絶されるが、合衆国 はSchemeに対して半分の票を、Common Lispに対して半分の票を投じる。日 本は、カナダと同様に、合衆国と共に投票するようである。ヨーロッパの人 達は団結している。Christian Queinnecが召集係であり、彼はやや力がない。 BSIは、専門的事項を通じてX3J13を止めようと試みるが、拒絶される。 - 初期のX3J13の会議は、ゴールのようなものに関係しており、Mathisは、言 語を変更する投票が行なわれないようにする意図を表す。一度CLOS委員会が 前進を行なおうとしているように見えると、一掃する委員会が形成され、 Larry Masinter (Xerox)がその担当に置かれる。この時点までは、Fahlman は会議に出席しており、Clinger(Tektronicsを代表して)とChailloux (INRIA)も同様である。一掃委員会の形成の直後、これらの人々は出席を止 める。 - いったん変更のための一掃方式があると、Common Lispへなされる多くの変 更がある。何百もの変更がなされ、多くは強制的な理由はないものである。 とりわけ、LOOPが採用され、関数型はきれいにされ、コンパイラマクロが採 用され、CLOSが採用され(1988)、コンディションシステムが採用され、そし て、もっともっと多くある[Steele, 1990c]。議論する価値があるのは、コ ンディション、繰り返し、CLOS、型、そしてあまりに広い範囲の変更を含む これらのいくつかである。 - 1989年、AIの冬が襲う。AI企業は、AIの能力を実際以上に高く評価し、その 代償を払う。LMIはこの頃に破産する。 - Sunは普通のハードウェア市場を支配する。彼らは、Symbolicsを不振にする。 1985年、彼らはSun 2を持ち、それは不十分だった。1986年、彼らはSun 3を 持ち、それは問題なかった。そして1988年、彼らはSun 4を持ち、それは非 常に良いものの始まりだった。IBM RTは巨大な失敗作である。HPは、PSLに 基づくCommon Lispへ移行しようとするが、あきらめて、代わりにLucidを選 ぶ。Common Lispは、BrooksとGabrielによって予言されたように、配達解決 (delivery solution)であるようにハックすることはできないことが明らか になり始める。 - 1989年、普通のハードウェア上の最初の非侵入的ガーベジコレクタが現れる (LucidとFranz) [Sobalvarro, 1988]。 - 1990年に、TIはLispゲームから脱落する。Xeroxは、1989年に、商業ベンチャ ーとしてInterlispを落とす。IBMは、そのLisp370に基づくCLを落とし、 Lucidを採用する。1990年、DECはそのLispを落とし、Lucidを採用する。AI の冬、および、商用のLispが統合と配達の問題を解決できないことは明らか である。さまざまなアプローチが試みられる(Lucidで木を揺らすことや、 Franzでの選択的荷積み)。これらは失敗する。1990年、Gabrielは、Europal での基調講演で、失敗の分析を試みる[?; ?]。 - 1988年、DARPAは、再びSchemeとCommon Lispの統合について議論するために、 Gabriel, Bobrow, Sussman, Fahlman, そしておそらくDARPA (Rosslyn)の他 の何名かの会議を呼びかける。ScherlisとSquiresがこれを駆動する。再度 失敗する。 - Schemeは、1989年にIEEE標準化を開始し、1991年に終える。最初の会議は 1989の初冬であり、Gabrielが出席する。彼は、標準化への反対と、その代 わりにX3J13へ加わることを主張するが、SchemeのCommon Lisp嫌いはあまり に強い。Schemeに対する2つの進路があるだろう: IEEE標準と、非公式のRn 報告書である。 - Schemeでは、衛生的マクロがRn Schemeの中に入るように見える。 - 1990年、EuLispグループは、EuLispの草案を作り出す。これは、以下のもの を持つ階層化された言語である: それは1-lispであり、モジュール、3つの 素晴らしい層に階層化されたCLOSに似ているOOPを持ち、そしてCommon Lisp の誤りの種々を一掃している。この仕事は、Padgetによって駆動されており、 彼が主に仕様を書いている。 - ISOでは、1990年までに、日本が、より強い声を持つようになり、プロセス は立往生する。Gabrielは、合衆国の代表団長を辞任する。Clingerは1988年 に辞職していた。Kiczalesが代理の代表である。 - 決定を行なうためのX3J13の最後の会議は1989年の1月であるはずだが、物事 を変えようとする熱情がだらだら長引く。これは、「みんながその上に小便 をしなければならない」症候群である。 - 1990年、Pitmanは、1989年にいなくなったChapmanを引き継いで編集長を申 し出る。1991年、彼は1300ページもの長さの最初の草稿を作り出す。残って いるLisp企業の一つ(Ibuki)は、CLtL1に戻ることを望んで、X3J13を取り消 そうとする。 [スケッチの節の終わり。] 分析 [以下のテキストは非常に不完全であり、書き入れられる必要がある。] 市場の圧力が受容グループを支配する。CLに対する受容グループは1989年には 衰え、多様化の疾風が、CLへの変更、追加の名の元に行なわれ、EuLispがつい に現れる(ヨーロッパが最初にAIの冬の打撃を受ける)。サイズや単純さのため に、受容グループのいくらかの部分はSchemeへ進む(例えば拡張言語の人々は CFIを好む)。CLの統合はInterlispを死に至らしめる。最初はLispマシンの印 が、後にはSunが、CLを前へ押す。ポストAIの冬時代は、再び小さなLispグル ープへ物事を縮ませたので、多様化の時代だと予期している。AI企業は、AIの 冬を、配達の解決策を提供しなかったLispグループのせいにするが、AI企業は、 利敵協力の恐れのために、ニーズをLisp企業へ決して伝えようとしなかった (大学人が企業家になるときに起こる平凡だが愚かな現象)。CLOSは、それ自体 が統合であり、そうでなければ停滞したCommon Lispへ印を加えた。Lispに対 する環境は決して真に標準化はされなかったが、AI企業は、環境に加えてUIや AIなどの大きなライブラリを供給した。 [スケッチの節の終わり。] 2.13 表現力 Lispは、自身が他の何よりも表現力に関心をもっていることを証明してきた。 特定のLispがどのように実装されているのかに熟達している一人の人が効率的 なプログラムを書けることを観察することで、このことがわかる。ここに、完 全に見事なコード片がある: (defun make-matrix (n m) (let ((matrix ())) (dotimes (i n matrix) (push (make-list m) matrix)))) (defun add-matrix (m1 m2) (let ((l1 (length m1)) (l2 (length m2))) (let ((matrix (make-matrix l1 l2))) (dotimes (i l1 matrix) (dotimes (j l2) (setf (nth i (nth j matrix)) (+ (nth i (nth j m1)) (nth i (nth j m2))))))))) 行列の中のセルを読んだり書いたりする式は、完全に無害であり、非常に速 く見える。しかし、これは遅い。なぜならnthは、本質的に呼び出されるたび 毎にリストをCDRで降りていくので、その第1引数の値に比例する時間がかかる からである(経験豊富なLispコーダは、数のインデックス上ではなくリストの セル上で繰り返すか、リストの代わりに配列を用いるだろう)。 ここでは、表現力は歪んでしまった。人々は、言語の中の操作は小さな単一 の時間を要すると期待し、何か理解するのが複雑なものであるとは思わない傾 向がある。だから、Lispが非常に表現力豊かであるまさにそのために、速いプ ログラムを書くことはとても難しいが、見事なプログラムを書くことは容易で ある。 3 ある特定の言語機能の進化 この節では、Lispに独特な、あるいは、Lispが独特に扱ういくつかの言語機能 の進化について議論する。 3.1 NIL(とT)の扱い ほとんど最初期から、Lispは、リストの終わりを示す区別されるオブジェクト としてシンボルnil(したがって、それ自身は空リストである)を用いてきた; この同じオブジェクトは、述語によって戻される偽値としても働く。McCarthy は、これらの決定は"やや気楽に"行なわれ、"後に不幸なことだと証明された" とコメントした。更に、最初期の実装は、0番地をNILの表現として用いるとい う伝統を確立した; McCarthyが再度コメントしたことには、"ポルノプログラ ミングを奨励することを除いて、0番地に特別な解釈を与えることは、その後 の全ての実装に困難を引き起こした"[McCarthy, 1978]。 nilの表現として0番地を用いることの利点は、多くのマシンは"0ならジャン プ"命令かその同等物を持っており、リストの終わりに対する素早くコンパク トなテストを許すことである。しかし、実装の難しさの一例として、PDP-10ア ーキテクチャを考えよう。それは、メモリ位置としてもアドレス付けされ得る 16個のレジスタ、あるいは"アキュムレータ"を持っていた。したがって、メモ リ位置0はレジスタ0だった。アドレス0はnilだったので、シンボルに対する標 準の表現は、レジスタ0の右半分がシンボルnilに対する属性リストを含むこと を要求した(そして左半分は、名前"nil"に対する文字列のような、他の情報の アドレスを含んでいた)。このように、実装の伝統は、あるレジスタを、レジ スタが少ない資源だったあるアーキテクチャに結び付ける結果になった。 後に、MacLispが、(car nil) = (cdr nil) = nilという慣習をInterlispか ら採用したとき、レジスタ0はまだ予約されていた; その2つの半分は、carと cdrの操作が、nilを特殊な場合として扱うことを必要としないように、値0を 含んでいた。しかし、シンボル上の全ての操作は、nilを特殊な場合として扱 わなければならなかったので、そのため、もはや他のシンボルと同じ表現を持 たなかった。これは、これが問題になるMacLispのアセンブリ言語カーネルの 中の全ての場所を見つけなければならなかったGuy Steeleにいくらかの困難を もたらした。今日では、彼は、それはむしろ実際には良いアイディアだったと 渋々認めている。確実に属性リストを得るための抽象の導入は、彼の最後の異 議を解決した(1975年2月7日のアイテム4): 1引数の新たなSUBRであるPLISTは、シンボルの属性リストを取り出すため に使われる; この関数は、NILを含む全てのシンボル上で動作するが、CDR は、non-*RSETモード[すなわち、エラーチェックをオフにして!]で非null のシンボルに対してのみ動作するだろう。同様の注意が、2引数の新たな SUBRであるSETPLISTに対して適用できる。(SETPLIST X (PLIST X))は何も しないべきである。 今日、いくつかのCommon Lisp実装は、コンスかシンボルのいずれかに対し て特別な場合を避けるために、オフセットデータ表現の複雑なシステムを用い ている; 各シンボルは、シンボルに対するデータがシンボルポインタによって アドレス付けられるメモリワードからではなく、アドレス付けされたワードの 2ワード後から始まるような方法で表現される。一つのコンスセルは、アドレ ス付けられた語(そのcdr)と、その後の語(そのcar)から構成される。この方法 で、同じポインタが、nilがシンボルとして、そして()がcarとcdrがどちらも nilである空リスト疑似コンスとして、どちらに対しても働く。 リストの終わりに対する素早いテストを用いることには危険がある; リスト は不正、すなわち、空リストでもコンスセルでもないオブジェクトで終わるこ とがわかるかもしれない。Interlispはその差異を分割し、スピードか安全か の選択をプログラマへ与える[Teitelman, 1978]: 多くのリストはNILで終わるが、例えば(A B . C)や、更に悪いことには、 数や文字列などのアトムで終わる特別なリストは、奇怪な効果を引き起こ し得る。したがって、我々は以下の実装上の決定を行なった: リストを通して繰り返す全ての関数、例えば、member, length, mapcな どは、無限のcdrループを引き起こすかもしれないデータ型に出会うこと に対する安全な用心として、慣習的なnullチェックではなく、nlistpチェッ クによって終了する… [イタリック体] 極度の効率を必要とするアプリケーションを用いるユーザのために[そ れらの脚注: NILチェックはたった1命令で実行され得る; Interlisp-10上 のnlistpは約8命令を必要とする。ただし、どちらもたった1ワードのコー ドを生成する。]、オープンにコンパイルし、NILチェックで終了する memb, last, nth, assoc, そしてlengthの速いバージョンを提供した… Fischer Blackは、1964年頃の早い時期に、NILと()の差異はプログラミング スタイルの問題であるとコメントした[Black, 1985]。空リスト、偽値、そし て"nil"という名前の普通のシンボルという3つの役割を別にするかどうかの何 年にもわたるかなりの議論があった; このような議論は、それを構成する人々 の多くがエレガンスと明快さに興味を持っているSchemeコミュニティでとりわ け激しかった。彼らは、以下のような構造物を (if (car x) (+ (car x) 1)) 悪い駄洒落だと考え、より明確な以下を好む。 (if (not (null (car x))) (+ (car x) 1)) 改訂改訂Scheme報告書[Clinger, 1985b]は、3つの別の量であるnil(単なる シンボル); 空リスト(); ブール偽値#!false(ブール真値#!trueも)を定義した。 しかし、興味深い妥協として、真/偽の値に対してテストする言語の全ての場 所は、()と#!falseの両方を偽と、その他全てのオブジェクトを真とみなした。 その報告書はコメントしている: 空リストは、単に歴史的な理由のために偽と見なされ、将来のSchemeの バージョンは、おそらくこのばかげたことを廃止するだろうから、プログ ラムはこれに依存すべきではない。 他のLisp方言に慣れているプログラマは、Schemeは、空リストをシンボ ルnilと同一と見なすばかげたことを既に廃止したことに気をつけるべき である。 アルゴリズム言語Scheme改訂改訂改訂報告書[Rees, 1986]は、#!falseと #!trueを#fと#tに短くし、似ているが(両方の意味で)もっと洗練された意見を 述べた: 空リストは、これを仮定する既存のプログラムや実装との互換性のため に偽と見なされる。 他のLisp方言に慣れているプログラマは、Schemeは、偽と空リストをシ ンボルnilから区別することに気をつけるべきである。 最近承認されたSchemeに対するIEEE標準は、#fと#tが標準の偽と真の値であ り、"#t, 空リスト, シンボル, 数, 文字列, ベクタ, そして手続きを含む"#f 以外の全ての値が真と見なされることを指定する[IEEE, 1991]。だからScheme コミュニティは、実際に、長い伝統に打ち勝ち、偽値、空リスト、そしてシン ボルnilの3つの観念を完全に分けた。それにもかかわらず、その疑問は討議さ れ続けている。 nilの疑問は、Common Lispの設計の中でも議論され、少なくとも一つの直接 貢献した実装であるNILでは、空リスト()はシンボルnilと同じではないという 決定を行なっていた(ある流行った冗談によると、NIL(New Implementation of Lisp)は、その言語の名前として働くことから自由になるために、NILの空リス トとしての役割の重荷をおろした!)。ついに、できは悪いが、過去と互換であ りたいという欲望[Raymond, 1991]が戦いを勝ちとった; これは、以下の電子 メールの断片にもっとも良く表現された: Date: Sunday, 14 March 1982 14:40-EST From: Symbolics Technical Staff Reply-to: Moon@SCRC-TENEX@MIT-MC To: Common-Lisp at SU-AI Subject: The T and NIL issues このメッセージが大変遅くなってしまい申し訳ない; 私の時間は、最近、 別のプロジェクトで完全につぶれていた。 我々は、TとNILの問題について、何回か内部で議論を行なった。我々が 完全に新たな言語を設計している場合、他の多くのLisp内のいぼ(あるい は美しいしみ)と同様に、きっとこれらについて再考するだろう(必ずしも 変えるわけではないかもしれないが、確実に再考するだろう)。しかし、T とNILを今変更することにより得られる利益は、変換のコストに比べて極 めて小さい。Symbolicsが容認できるこれらの問題への唯一の解決法は、 現状を維持することである。 現状維持を要約すると: NILはシンボルであり、空リストであり、そし て区別される"偽の"値である。SYMBOLP, ATOM, そしてLISTPはそれに対し て真である; CONSPはそうではない。NILのCAR, CDR, そしてEVALはNILで ある。NILは関数としても、変数としても、使われてはならない。NILは属 性リストを持つ。Tはシンボルであり、半述語ではない(すなわち、真であ る時に"意味のある"値を戻さない)述語によって用いられるデフォルトの "真の"値である。TのEVALはTである。Tは変数として使われてはならない。 Tは、FORMATのようなある種の関数によってキーワードとして認識される。 LISTPの振る舞いは、我々[Symbolics]がずっと前に同意した現状維持へ の変更であり、我々がCommon Lispが何らかの非互換な変更を行なわない ことを待っていなかったとしたらずっと前に実装を終えていただろう。現 状維持は、NILが属性リストを持つことである; しかし、この点は、NILが 与えられた時には属性リスト関数はエラーになるべきだと誰かが強く感じ る場合、おそらく交渉の余地があるだろう。 CASEQとSELECTQで文法上のキーワードとしてTを使うことは、Common Lispでの置き換えであるCASEに持ち越されるべきではない。それは、COND でのTについての慣習の誤解に基づいており、間違いなく、言語の理解可 能性に何も加えていない。 TとNILは、Lispでの他の何百もの予約語と、それらの何ダースかは変数 として、残りの多くは関数として予約されているのだが、ちょうど同じよ うなものである。特別に予約されたシンボルとしてではなく、通常のシン ボルとしてこれらの名前を使いたいすべての特定のプログラムは、パッケ ージを使うことで容易にそれを行なえる。ポータブルなパッケージシステ ムの中に、予約されているNILがお望みなら"GLOBAL:NIL"ではなく"()"と 印字されるようにし得るパッケージオプションがあるべきである。 ある有名な例外、Richard M. Stallmanによって1970年代に書かれたPDP-11 のためのLispシステム(そのシステムでは、シンボルnilではなく数0が空リス トと偽として使われた)を除いて、Lisp実装者がnilと数0を同一視したくなっ たことはないことは注目に値する。これを、APL [Iverson, 1962]での偽と真 としての0と1の使用、あるいは、C [Kernighan, 1978]での偽とヌルポインタ としての0の使用と比べよう。これらの言語のどちらも、McCarthyがLispにつ いて行なった駄洒落と悪いプログラミングの実践に関するのと同種のコメント を引き起こした。 これは、言語設計のこのような小さな点に、この論文では多くの議論を費や している様に読者には見えるかもしれない。しかし、ここで取られたスペース は、数年にわたってLispコミュニティによってこの点について実際に費やされ た議論の時間とエネルギーの比率を正確に反映している。それは、表現力対清 潔さ、そして異なる明快さの観念についての議論である。Lispが強い型付けを 強制しないとしても、コードの中で型の規律を維持することを好むプログラマ もいて、(if (car x) . . . )の代わりに(if (not (null (car x))) . . . ) と書く。そうでない人は、このような余分な散らかしは、改善どころか明確さ を減じていると主張する。 3.2 繰り返し Lispは、そのP.R.によれば、制御構造を表現する主な手段として、条件付き実 行と再帰的に定義された関数を伝統的に用いてきた一方、実際は、繰り返しを もっと便利にする様々な文法の工夫の導入を度々、そして継続して試みてきた。 これは、ALGOLのような言語で発見されたプログラミングのスタイルをエミュ レートしたいという欲望によって、また、いくつかのコンパイラはときどき末 尾再帰呼び出しを最適化するだろうが、1980年代の良いSchemeとCommon Lisp コンパイラの時代まで、プログラマはそれに頼ることができなかったので、処 理性能が課題だったという事実によって駆動されたのかもしれない。 おそらく、最も単純な特別な繰り返し構文が、MacLispに導入された最初の doループ(in March, 1969)によって例示されるだろう: (do var init step test . body) は、以下と同じ意味である (let ((var init)) (block (when test (return)) (progn . body) (setq var step))) したがって、以下のFortranのDOループは DO 10 J=1,100 IF (A(J) .GT. 0) SUM = SUM + A(J) 10 CONTINUE 以下のように表現され得るだろう (DO J 1 (+ J 1) (> J 100) (WHEN (PLUSP (A J)) (SETQ TOTAL (+ TOTAL (AREF A J))))) (もちろん、Lispの配列は通常は1からではなく0から始まるので、 (DO J 0 (+ J 1) (= J 100) (WHEN (PLUSP (A J)) (SETQ TOTAL (+ TOTAL (AREF A J))))) が、実際にはもっと慣用的な表現であることは除く) この"古いスタイルの"MacLispのdoループは、Lispに導入された最初の繰り 返しの文法というわけでは決してなかった; それに言及するのは、単にそれが 最も単純だからである。Interlisp CLISPの繰り返し文は、それ以来再発明さ れてきたもっと典型的なスタイルの最初の例だった: (FOR J←0 TO 99 SUM (A J) WHEN (PLUSP (A J))) これは、副作用によって変数TOTALに蓄積するのではなく、その値としてsumを 戻す(Algolスタイルの文法のこれ以上の議論は3.7.1節を参照)。 マクロ、あるいはCLISPのような他のコード変換機構は、この種の拡張を特 に容易にする。Interlispでの努力はまとめられたが、他のLisp方言(MacLisp も例外ではない)では、一人の局所的なウィザードか別の人が、Lispでの繰り 返しプロセスに対する何らかの素晴らしい文法をでっちあげる実例が何度も繰 り返された。通常、それは、Algolのような言語で見つかる疑似英語のキーワ ードの種類によって特徴付けられるが、スタンフォードでのあるバージョンは、 自家製のキーボード上の拡張ASCII文字集合にもっと依存していた。これは、 非常に関連する文法、典型的には、キーワードFORあるいはLOOPで始まるもの の急増を導き、それは多くのプログラマを引き付けたが、機能が固まったとき に他の人達の胃をむかつかせた。 繰り返し文法に対するこれらの強い異なる美学的反応のために、ループマク ロを含めるかどうかの問題は、Common Lispの初期の設計での主要な政治的な 戦いになった。Lisp Machineの人々は一般にその採用に好意的であり、Scott Fahlmanは断固として反対した。Guy Steeleはおそらくやや弱くだがFahlmanを 支持した。その結果は妥協となった。Common Lispの最初の定義[Steele, 1984]は、完全に最小の機能だけを持つループマクロを含んだ: それは、特別 なキーワードを許さず、部分フォームの列を無限の繰り返しを表現することだ けが許されていた。それは場所取りであると理解され、何らかの本格的な繰り 返しの文法へ拡張できるように名前loopを予約した。ANSI委員会X3J13は、MIT やLisp Machineで使われていたもの(それはInterlispで使われたものと大きく は違わなかった)に基づく、わずかにきれいになったバージョンのloop [Steele, 1990c]に同意し採用した。 そのプロセスの中で、X3J13は、その間に現れた繰り返しへの2つの別のアプ ローチも考慮した: シリーズ(Richard Watersによって提案された)、そして、 ジェネレータとギャザラ(Pavel CurtisとCrispin Perdueによる)である [Steele, 1990c; Waters, 1984; Waters, 1989a; Waters, 1989b]。上で示さ れたFortranのDOループの例は、シリーズを使って以下のように表現できるだ ろう: (collect-sum (choose-if #'plusp (#M(lambda (j) (a j)) (scan-range :start 0 :below 100)))) これは関数型スタイルであり、APLを思い出させる: +/(T>0)/T←A[ι100] シリーズのプリミティブと、それらに許される合成は、実行時に際限なく大き な中間データ構造を必要とせずに効率的な繰り返しコードへ常にコンパイルさ れ得るように、賢明にも制限されている。ジェネレータとギャザラは、副作用 によって連続する値のソースあるいはシンクとして働くそれぞれが入力あるい は出力ストリームのように見えるように、(実行時の状態のコストで)シリーズ をカプセル化するメソッドである。したがって、以下は、 (generator (choose-if #'plusp (#M(lambda (j) (a j)) (scan-range :start 0 :below 100)))) 抽出関数next-inへ与えたときに、(A 0), (A 1), などから生じる連続する正 の数を渡すオブジェクトを作る。これは、人に、Conniverの可能性リスト (possibilities lists)[McDermott, 1974]、あるいは、Alphardのジェネレー タ[Shaw, 1981]を思い出させるが、直接のつながりはないことを我々は知って いる。 かなりの討論の後で、X3J13はシリーズとジェネレータの開発を称賛したが、 標準化の目的に対しては拒絶し、それらに時間というテストをまず受けさせる ことを選んだ。 議論に値する別の繰り返し構文は、1972年の3月に導入された、MacLispの "新たなスタイルの"doループである: (do ((var1 init1 step1) (var2 init2 step2) ... (varn initn stepn)) (test . result) . body) これは、全てのinitフォームを評価し、対応する変数varを結果の値へ束縛す る。それから、以下の順序を繰り返す: testフォームの評価が真の値を生じる 場合、resultフォームを評価し、その最後のものの値を戻す; そうでなければ、 bodyフォームを順に実行して繰り返す。 この構文の美しさは、キッチュな疑似英語のキーワードを使わずに、初期化 や多数の変数をステッピングできることである。恐ろしい部分は、区切りとし て多数のレベルの括弧を使い、それらを正しく理解するか、そうでなければ奇 妙な振る舞いを我慢するか、というところである; 頑固なLisperだけが、この ような文法を愛せるだろう。 文法上の議論はさておき、あらゆるプログラミング言語で、1つだけの変数 をステッピングするループはほとんど役にたたないことを認めるために、何か しら言われていることがある。1つの変数が連続する値を生成するために使わ れ、他の変数が結果を蓄積するために使われるのが、ほぼ大抵の場合である。 ループの文法が生成されている変数だけを変更する場合、蓄積される変数は、 (Fortran の例のように)代入文か、あるいは何らかの他の副作用によって"手 動で"変更されなければならない。多変数のdoループは、生成と蓄積の間の本 質的な対称を反映しており、繰り返しを明示的な副作用なしで表現できる: (define (factorial n) (do ((j n (- j 1)) (f 1 (* j f))) ((= j 0) f))) この形式のdoループが空の本体を持ち、実際の仕事の全てをステップフォーム の中で行なうことは、実際に稀ではない。 progとsetqを用いるこのdo構文の極めて明らかな翻訳がある一方で、副作用 から自由な明快なモデルもある: (labels ((the-loop (lambda (var1 var2 ... varn) (cond (test . result) (t (progn . body) (the-loop step1 step2 ... stepn)))))) (the-loop init1 init2 ... initn)) 実際、これはScheme [IEEE, 1991]によって採用されたdoの定義と同じであり、 変数を副作用ではなく束縛で更新を行なうように要求することで、未解決の曖 昧さを解決する。したがって、繰り返しプロセス全体は副作用から自由である。 ORBIT [Kranz, 1986]のような良いSchemeのコンパイラや、良いCommon Lispの コンパイラの出現と共に、この副作用のない変換の結果をコンパイルすると、 PROGとSETQのモデルから期待されるものと正確に同じ効率の機械語が生成され る。 3.3 マクロ マクロは、短いMIT AI Memo [Hart, 1963]によって1963年にTimothy P. Hart によってLispに導入されたように見える。ここで、その全体を引用する[許可 は要求中]: LISP 1.5では、特殊形式は、3つの論理的に別の目的のために使われて いる: a) 連想リストに到達するため、b) 関数が不定の数の引数を持てる ようにするため、そしてc)引数が評価されないようにするためである。 新たなLISPインタプリタは、連想リストをSPECIAL型あるいはAPVAL型の 実体とすることで、ニーズ(a)を容易に満たせる。使用法(b)と(c)は、定 義にMACRO命令エクスパンダを組み込むことで置き換え得る。私は、その ようなエクスパンダを提案する。 1. マクロ定義の属性リストは、インジケータMACROを持ち、その後に1 引数の関数、マクロ名で始まるフォームが続く。その値は、全ての 関数定義の元のフォームを置き換える。 2. 関数macro[l]は、ちょうどdefine[l]が関数を定義するようにマクロ を定義する。 3. defineは、マクロ展開を作るように修正される。 例: 1. 既存のFEXPR csetqはマクロ定義で置き換わるかもしれない: MACRO (( (CSETQ (LAMBDA (FORM) (LIST (QUOTE CSET) (LIST (QUOTE QUOTE) (CADR FORM)) (CADDR FORM)))) )) 2. 新たなマクロstashは、PROGの中で頻繁に見つかるフォームを生成す る: x := cons[form;x] マクロstashを使うと、上の代わりに以下のように書けるだろう: (STASH FORM X) stashは以下によって定義されるだろう: MACRO (( (STASH (LAMBDA (FORM) (LIST (QUOTE SETQ) (CADAR FORM) (LIST (CONS (CADR FORM) (CADAR FORM))) ))) )) 3. 新たなマクロは、古いマクロで定義されてもよい。Enterは、プログ ラム変数の値として格納されているテーブル(ドットペア)へ新たな 値を加えるためのマクロである。 MACRO enter[form] ≡ list[STASH;list[CONS;cadr[form]; caddr[form];cadddr[form]] それに付随して、マクロを使うと、90 LISPコンパイラが誕生時点で 存在するfexprだけしか知らないことから生じる現在の困難が軽減さ れるだろう。 関数macroを定義するマクロは容易に定義される: macro[l] ≡ deflist[l;MACRO] 新たなdefineは少し難しい: define[l] ≡ deflist[mdef[l];EXPR] mdef[l] ≡ [ atom[l] → l; eq[car[l];QUOTE] → l; member[car[l];(LAMBDA LABEL PROG)] → cons[car[l];cons[cadr[l];mdef[caddr[l]]]]; get[car[l];MACRO] → mdef[get[car[l];MACRO][l]]; T → maplist[l;λ[[j];mdef[car[j]]]]] 4. selectに対するマクロは、関数が任意の数の引数を持てるようにす る手段としてのマクロの使用法を例証している: MACRO select[form] ≡ λ[[g]; list[list[LAMBDA;list[g];cons[COND; maplist[cddr[form];λ[[l]; [null[cdr[l]] → list[T;car[l]]; T → list[list[EQ;g;caar[l]];cadar[l]]]]] ]];cadr[form]]][gensym[]] Hartの提案については、注目する価値がある点がたくさんある。非常に多く の他の当時のマクロプロセッサが行なっていたようにテンプレートへの置き換 えに頼るのではなく、マクロ展開が、任意のユーザ定義の関数によって計算さ れ得るようにしている。彼は、マクロはfexprとは異なり、コンパイラの部分 のそれぞれに対する特別な知識が不要であることを特に言及した。マクロは、 関数定義の時に展開されるのであり、関数が解釈あるいはコンパイルされる時 にその場で展開されるのではない。S式とM式の文法の間の切り替わりに注意し よう。STASHマクロは、Interlisp [Teitelman, 1978]や、Lisp Machine Lisp を経由して後にCommon Lispの中に見出されるPUSHマクロの同等物である; 動 詞"stash"は、1960年代には普通に使われていた。mdefの定義には、2つのそれ ほど重要ではないバグがある: 第1に、PROGが正しく扱われていない。なぜな ら、PROG形式の中のすべての文を処理するのに失敗するからだ; 第2に、COND が特別に扱われておらず、変数がマクロと同じ名前を持ち、その変数がCOND節 のテスト部分として使われる場合、誤りになり得る(おそらく、これは見落と しだったか、あるいは、これほど異なる2つの目的に対して1つの名前を使うよ うな悪趣味を持つ人がいるかもしれないということが、Hartには全く思い浮か ばなかったのだろう)。最後の例は、引数フォームの複数回評価を避けるため に、一時的な束縛のために新たな名前を生成するテクニックを例証している。 最後に、Hartは、自身のメタ言語として働くようにLispの力を利用することを ユーザに奨励することで、その言語への誤解を招くほど単純な変更を用いて驚 くべき表現力の増加を達成した。 Hartのマクロ言語は、その後、Q-32 [Saunders, 1985b]に対するLispシステ ムで使われた。コンパイラコード[Saunders, 1985a, p. 311]の中のMDEF関数 を検査すると、PROG文を処理する中でのエラーは修正されていることがわかる: mdef[caddr[l]]はmdef[cddr[l]]で置き換えられていた(実際は、これは、Hart がもともと意図したことかもしれない; [Hart, 1963]では、"a"は別の文字の 上に訂正として手で書かれたように見える。おそらく、タイピストが印刷上の 誤り(mdef[ccddr[l]])を犯し、その後、間違った訂正がなされたのだろう)。 不幸にも、mdef[cddr[l]]の使用には独自の問題がある: その値がLAMBDA式に よって戻される変数、あるいは、PROGの先頭でのタグは、マクロの名前として 間違って認識されるかもしれず、したがって、LAMBDAあるいはPROGの本体をマ クロ呼び出しとして扱うかもしれない。難しい、難しい - しかし、今日では、 我々はこの種のことについて注意深くなろうとしている。 類似の種類の計算されたマクロがMIT PDP-6 Lispに現れたが、マクロ呼び出 しは、コンパイラ、あるいはインタプリタによって発見された時にその場で展 開された。インタプリタの場合、関数呼び出しフォームの中で明示的に名付け られた関数が、属性リスト上に(EXPR, SUBR, LSUBR, FEXPR, あるいはFSUBRの ような関数インジケータの1つではなく)MACRO属性を持つことがわかったとき、 その関数定義は、引数としてもともとのマクロ呼び出しフォームを与えられ、 呼び出しの場所で評価される別のフォームを戻すと期待された。PDP-6 Lispメ モ[PDP-6 Lisp, 1967]の中で与えられている例は以下の通りである: (DEFPROP CONSCONS (LAMBDA (A) (COND ((NULL (CDDR A)) (CADR A)) ((LIST (QUOTE CONS) (CADR A) (CONS (CAR A) (CDDR A))))) MACRO) これは、Common Lispの関数list*と実際上は同じマクロを定義した。関数を定 義するためにDEFPROPを使っていること、単一の引用符文字ではなくQUOTEを使っ ていること、そして、現在はほとんど一般的な慣例となっている2番目のCOND 節でのTが省略されていることに注意しよう。 この考えの長所は、マクロを使い、後でそのマクロを定義(あるいは再定義) する関数を定義できることだった; マクロ呼び出しは、常に、最新のマクロ定 義を使うだろう。しかし、欠点は、インタプリタが繰り返される度に同じマク ロ呼び出しを常に再展開しなければならず、実行速度を遅くすることだった。 置換マクロと呼ばれる工夫が、MacLispユーザの間でまもなく一般的になった; それは、ユーティリティ関数DISPLACEを伴っていた: (DEFUN DISPLACE (OLD NEW) (RPLACA OLD (CAR NEW)) (RPLACD OLD (CDR NEW)) OLD) それから、以下のように書く人がいるかもしれない: (DEFPROP CONSCONS (LAMBDA (A) (DISPLACE A (COND ...))) MACRO) その効果は、それを展開で置き換えるために、マクロ呼び出しの元のリスト構 造を破壊的に変更するものだった。 この、すべてがあまりに賢いトリックは、自身の欠点を持っていた。第1に、 マクロが(数あるいは変数参照のような)アトムへ展開する必要がある場合には 失敗した; マクロの作者は、FOOの代わりに(PROGN FOO)を生成することを学ん だ。第2に、置き換え前のマクロへの呼び出しの後にそのマクロが再定義され た場合、それに続く呼び出しの実行は、新たな定義を使わないだろう。第3に、 そのコードは修正された; 元々マクロ呼び出しを含んでいたコードをプリティ プリントすると、元々のマクロ呼び出しではなく、その展開を表示するだろう。 この最後の欠点は、MacLisp環境が非常に強固にファイルベースだったので我 慢できた: 置換マクロは、コアの中のプログラムのコピーだけを修正した; そ れは、あるファイルの中にテキストとして存在すると考えられる原定義には影 響しなかった。この種の置換マクロは、Interlispでは我慢できなかっただろ う。 1978年ごろ、Lisp Machine Lispは、置換テクニックへ改良を導入した: (defun displace (old new) (rplacd new (list (cons (car old) (cdr old)) new)) (rplaca old 'si:displaced) new) (defmacro si:displaced (old new) new) アイディアは、リスト(si:displaced macro-call expansion)によってそのマ クロ呼び出しが置換されるというものである。マクロsi:displacedは第2引数 のフォームを透過的に戻すので、すべては、展開自身がマクロ呼び出しを置き 換えたかのように振る舞う。si:displacedへの呼び出しの展開は自由ではない 一方で、元のマクロ呼び出しを頻繁に再展開するよりは恐らく安価だろう(そ うでなければ、マクロ作者はdisplaceを使うべきではない)。Lisp Machineの プリティプリンタはsi:displacedへの呼び出しを認識し、元のマクロ呼び出し だけを印字する。 1960年代に戻ると: DEFPROP記法は、MacLispでDEFUN記法によってすぐに置 き換えられた[White, 1969-1982, Jon L White, item 1 of March 1, 1969]: DEFUNは、関数を定義するために使われるFSUBRである。たとえば、 (DEFUN ONECONS (X) (CONS 1 X)) は、以下と同等であり、 (DEFPROP ONECONS (LAMBDA (X) (CONS 1 X)) EXPR) そして、 (DEFUN SMASH FEXPR (L) (RPLACD L NIL)) は、以下と同等である。 (DEFPROP SMASH (LAMBDA (L) (RPLACD L NIL)) FEXPR) DEFUNの新たな機能は、関数定義の一番最後で括弧をつりあわせることを あまり心配する必要がないことである。なぜなら、それがEXPRである場合 はタイプタグが削除されてもよいし、それ以外の何かである場合はDEFUN リストの先頭付近に現れるからである。また、LAMBDAが直接挿入される必 要はない。 どこか他のところで、Whiteは更に注記した[?]: [DEFPROP]は、MacLispで関数を定義する通常の方法だったが、DEFUNは、 そのような定義が行なわれつつあることをもっと明確に示す方法を提供す るために、そして、属性リストと関数表現の構造の中で実験できるように するために、実装された。 DEFUN自身はマクロとして容易に実装できたかもしれないが、そうではなかっ た; なぜなら、それは非常に頻繁に使われたので、効率の理由で(コンスする ことを避けるために)FSUBRとして手でコード化され、コンパイラによって特別 に認識された(Common Lispは、defunはマクロであると遂に指定した)。 BBN Lisp [Teitelman, 1971]は、3種類のマクロを持っていた: 開かれる (open)もの、計算される(computed)もの、そして置換(substitution)である (以下に記述される)。マクロ定義は、その名前の属性リストの中のMACRO属性 の下に格納された; 属性値のフォームは、3つのタイプのどのマクロかを決定 した。元は、3つのタイプのすべてはコンパイルされたコードでのみ有効だっ た。しかし、最終的には、BBN LispがInterlisp [Teitelman, 1978]になった 後、MACROTRANと呼ばれるDWIMハックが加えられ、3つのタイプのマクロのすべ てがインタプリトされるコードで有効になった。インタプリトされている関数 呼び出しが"未定義関数"エラーになる場合、DWIMシステムが割り込むだろう。 MACROTRANは制御を獲得し、そのマクロを展開し、そして結果として生じる展 開を評価するだろう。Interlispのマニュアルは、インタプリトされるマクロ はDWIMが有効にされている場合にのみ動作するだろうときちんと注記している。 これを、プリミティブな言語機能としてインタプリタの中に(コンパイラと同 じく)直接マクロを作るMITのアプローチと対比してみよう。 BBN-Lispのオープンマクロは、マクロ名がラムダ式によって置換されるよう にしただけであり、その関数は"開かれて"あるいはインラインでコンパイルさ れるようにした。ここに、ABSに対するオープンマクロ定義がある: (LAMBDA (X) (COND ((GREATERP X 0) X) (T (MINUS X)))) もちろん、これは、関数定義と正確に同じフォームを持つ。 BBN-Lispの計算型マクロ(computed macro)は、MIT PDP-6 Lispと似た種類の ものだったが、エクスパンダ関数がマクロ呼び出しの全体ではなくCDRを受け とることが異なった。ここに、LISTに対する計算型マクロがある: (X (LIST (QUOTE CONS) (CAR X) (AND (CDR X) (CONS (QUOTE LIST) (CDR X] 先頭のXは、マクロ呼び出しフォームのCDRへ束縛されることになる変数の名前 である。定義の中での閉じているスーパー角括弧の使用にも注意しよう(2.3節 を参照)。 BBN-Lispの置換マクロ(substitution macro)は、単純なパターン(パラメー タリスト)と置換テンプレートから成っていた; マクロ呼び出しの部分フォー ムは、対応するパラメータ名のテンプレート中の出現に対して置換された。 ABSに対する置換マクロはこのようになるだろう: ((X) (COND ((GREATERP X 0) X) (T (MINUS X)))) しかし、呼び出し(ABS (FOO Z))は以下へ展開され、 (COND ((GREATERP (FOO Z) 0) (FOO Z)) (T (MINUS (FOO Z)))) (FOO Z)を複数回評価することになるが、(FOO Z)が高価な計算だったり副作用 を持つ場合は残念なことになるだろう。対照的に、オープンマクロを用いると、 呼び出し(ABS (FOO Z))は以下へ展開され、 ((LAMBDA (X) (COND ((GREATERP X 0) X) (T (MINUS X)))) (FOO Z)) (FOO Z)を正確に一度評価するだろう。 しかし、複数回の評価を避けるためにしばしば注意が必要であるにもかかわ らず、マクロ定義に対するパターン/テンプレート方法論はたいへん便利であ り、視覚に訴えるものがある。実際、パターンマッチングとテンプレートの方 法論は、1960年代と1970年代を通じて人工知能のための言語の開発で広まって いたトピックだった; 4節を参照せよ。下の方で、テンプレートに基づくマク ロのトピックに戻ってくるだろう。 驚くべきことではないが、Muddle [Galley, 1975]はPDP-6 Lispにとてもよ く似たマクロ機構を持っていたが、1つだけ僅かな違いがあった。マクロ展開 関数は、引数としてマクロフォームと共に呼び出されるのではなく、フォーム のCDRへ適用された。このことは、Muddleの複雑な引数リストのキーワードが 動作し始めるようになることを可能にし、Interlispの置換マクロに対するよ うなある種の単純な種類のパターンマッチングを許した: .N>>> それにもかかわらず、計算型マクロに対するのと同様に、結果を苦心して構築 する必要があった。を展開した結果は>になるだろう (Muddleの.Xは、、すなわちXの局所値に対する単なるリードマクロの 短縮であることに注意)。 MacLispがPDP-6 Lispから発展してきた頃、MacLispコミュニティは多様化し、 マクロを定義するための種々の方法論を生み出した。INCのような単純なマク ロは、若干かさばるにしても(確かにMuddleやInterlispよりは不格好である)、 概念的には書くことは複雑ではなかった: (DEFUN INC MACRO (X) (LIST 'SETQ (CADR X) (LIST 'PLUS (CADR X) (COND ((CDDR X) (CADDR X)) (T 1))))) 引数フォームの自動的な分解("分配(destructuring)")の欠如が、結果を構築 するコードの中でCAR, CDR, そしてCONDの多数の使用をもたらすことに注意し よう。ある人は構築から分配を切り離すためにLETを使える: (DEFUN INC MACRO (X) (LET ((VAR (CADR X)) (N (COND ((CDDR X) (CADDR X)) (T 1)))) (LIST 'SETQ VAR (LIST 'PLUS VAR N)))) しかしLETは - 最初に発明され各サイトでローカルに再発明された、それ自身 がマクロである - MacLispの世界へ後に来た物だった; Lisp Archiveによると、 それは、1979年、DEFMACROや複雑なLisp MachineのDEFUN引数文法と同じ頃に、 Lisp-Machine LispからPDP-10 MacLispへ遡及的に採り入れられた。1970年代 の間に行なえた最良のことは、LAMBDA式を使うことだった: (DEFUN INC MACRO (X) ((LAMBDA (VAR N) (LIST 'SETQ VAR (LIST 'PLUS VAR N))) (CADR X) (COND ((CDDR X) (CADDR X)) (T 1)))) そして、多くのプログラマは、これは少しも魅力的ではないと感じた。結果と して、複雑なマクロを書くことはかなり難しい技術であり、ウィザードは、そ れぞれ別々のマクロ定義のスタイルを開発した。以下は、Jon L Whiteからプ ログラマへの、あるアドバイスである[White, 1969-1982, May 1974]: 以下を行なったとしよう: (SETQ BARODD (ARRAY NIL FIXNUM N) BAREVEN (ARRAY NIL FIXNUM N)) この時点で、BARODDとBAREVENの両方が、値として配列ポインタを保持 する.... 2つのマクロを定義しよう: (DEFUN MACRO BO (X) (SUBST (CADR X) 'INDEX '(ARRAYCALL FIXNUM BARODD INDEX))) (DEFUN MACRO BE (X) (SUBST (CADR X) 'INDEX '(ARRAYCALL FIXNUM BAREVEN INDEX))) それから、以下のようにBARODDとBAREVENを埋めることができるだろう: (DO J 1 (1+ J) (> J N) (STORE (BE (1- J)) (* 2 J))) (DO J 0 (1+ J) (NOT (< J N)) (STORE (BO J) (1+ (* 2 J)))) 確かに、これは多くのタイピングを省く。しかし、このようなMACROを 用いて短縮したいほど多くの配列変数を持っているとしよう。すべての マクロ定義をタイプ入力するのは、退屈な繰り返しになり得るだろう。 以下のマクロを定義するマクロと、そのいくつかの使用を考慮しよう: (DEFUN MACRO ABBA (Y) (SUBLIS (LIST (CONS 'SHORT (CADR Y)) (CONS 'LONG (CADDR Y)) (CONS 'TYPE (CADDR Y))) '(DEFUN MACRO SHORT (X) (SUBST (CDR X) 'INDEXLIST '(ARRAYCALL TYPE LONG . INDEXLIST))))) 今なら、BEのためのマクロを生み出すためにABBAを使うかもしれないが、 マクロのフォームが若干異なることに注意しよう - マクロ出力の主要 なボディは、普通のリストではなくドットリストであるように見える。 この結果、次元の数が変わる配列は、同じスーパーマクロによって定義 される短縮を持つかもしれない。 (ABBA BO BARODD FIXNUM) は以下へ展開し、 (DEFUN MACRO BO (X) (SUBST (CDR X) 'INDEXLIST '(ARRAYCALL FIXNUM BARODD . INDEXLIST))) それから、BOに対する適切なマクロ定義を引き起こす。それから、期待 通りに、(BO J)は以下へ展開する: (ARRAYCALL FIXNUM BARODD J) しかし、以下のように定義される2次元のハッシュ配列HASHを考えよう: (SETQ HASH (ARRAY NIL T 37 37)) それなら、(ABBA HA HASH T)は、(HA 3 (+ N 2))が (ARRAYCALL T HASH 3 (+ N 2))へ展開するようにHAを定義する。 Guy Steeleは、洗練されたマクロやマクロを定義するマクロのファイ ルを蓄積してきた。興味がある人は、彼に相談できるかもしれない。 どのくらい容易にこれが手に負えなくなるかを見るために、単純なFORルー プに対するマクロを考えよう。典型的な使用はこのようなものだろう: (for a 1 100 (print a) (print (* a a))) これは、以下へ展開すべきである: (do a 1 (+ a 1) (> a 100) (print a) (print (* a a))) これは、ありふれたシンタックス上の変形で、単純だが便利であり、Fortran のDOループに似たシンタックスをほんの少し一般的な"古いスタイルの" MacLispのDOループ(3.2節を参照)の言葉で定義している。1970年代初期の MacLispでは、以下のように定義するかもしれない: (defun for macro (x) (cons 'do (cons (cadr x) (cons (caddr x) (cons (list '+ (cadr x) 1) (cons (list '> (cadr x) (cadddr x)) (cddddr x))))))) これは、このような単純な変形のために書くには多過ぎる。 最終的に、様々なMacLispのサイトの導師たちは、似ているがあまり互換性 がない、マクロを定義するマクロを何ダースも開発した。いくつかこのような パッケージが同じサイトで、各セクトの信者が何であれ彼らのウィザードが開 発したものを使うことは珍しくはなかった。このようなパッケージは、通常、 引数フォームの分配や結果のフォームの構築のためのツールを含んでいた。結 果のフォームの構築のためのツールは、2つの主要なカテゴリーに分けられた: 置換と疑似クォートである。置換テクニックは、指定された値によって置き換 えられることになっているテンプレートの中で、ある種のシンボルの独自の記 述を必要とした。疑似クォートは、置き換えの値を計算するためのコードが、 テンプレート自身の中に生じることができるようにした; テンプレートは、そ のテンプレートの中で特別にマークされた場所であることを除いて"ちょうど quoteのよう"であるオペレータへの呼び出しに囲まれていたので、疑似クォー トと呼ばれた。 マクロは、Lisp-Machine Lispで大きく前進し、様々なマクロ定義のテクニッ クを、MacLispコミュニティの至るところで採用された2つの標準化された機能 に、そして最終的にはCommon Lispに統合した。マクロを定義するオペレータ DEFMACROは、任意の深さまでのリスト構造の分配を提供した; バッククォート 機能は、便利で簡潔な疑似クォート機構を提供した。以下は、DEFMACROだけを 用いているFORマクロの定義である: (defmacro for (var lower upper . body) (cons 'do (cons var (cons lower (cons (list '+ var 1) (cons (list '> var upper) body)))))) 元のフォームの部分を名付けられることに注意しよう。バッククォートの疑似 クォートシンタックスを用いると、それはテンプレートのコピーを作り、コン マによってマークされたそれぞれの場所にそれに続く式の値を埋めるものだが、 とても簡潔で読みやすい定義を得る: (defmacro for (var lower upper . body) `(do ,var ,lower (+ ,var 1) (> ,var ,upper) ,@body)) スプライシングを表すために,@を使っていることに注意しよう。 バッククォートシンタックスは、ネストされるときに特にパワフルだった。 これは、主にマクロを定義するマクロの中で発生した; そのようなものは主に ウィザードたちによってコード化されたので、ネストされるバッククォート式 を書いたり解釈したりする能力は、まもなくある種の神秘に包まれた。MITの Alan Bawdenは、Lisp Machineの初めの頃に、バッククォート名人としての特 別の名声を獲得した。 ネストされるバッククォート使用の一例として、上で示されたマクロを定義 するマクロABBAの以下のバージョンを考えよう: (DEFMACRO ABBA (SHORT LONG TYPE) `(DEFMACRO ,SHORT (&REST INDEXLIST) `(ARRAYCALL ,',TYPE ,',LONG ,@INDEXLIST))) これはずっと短く、(少なくともBawdenにとっては)理解しやすい。トリッキー な部分はイディオムであるコンマ-クォート-コンマであり、疑似クォートと同 様に普通のクォートを持つ必要性を例証している。 これらの式の多くは、内から外へ容易に理解され得る。 以下の内側のバッククォート式は、 `(ARRAYCALL ,',TYPE ,',LONG ,@INDEXLIST) 以下と同等であり、 (LIST* 'ARRAYCALL ',TYPE ',LONG INDEXLIST) もちろん以下とも同等である。 (LIST* 'ARRAYCALL (QUOTE ,TYPE) (QUOTE ,LONG) INDEXLIST) したがって以下は、 `(DEFMACRO ,SHORT (&REST INDEXLIST) `(ARRAYCALL ,',TYPE ,',LONG ,@INDEXLIST)) 以下を意味し、 `(DEFMACRO ,SHORT (&REST INDEXLIST) (LIST* 'ARRAYCALL ',TYPE ',LONG INDEXLIST)) それは以下と同等であり、 (LIST 'DEFMACRO SHORT '(&REST INDEXLIST) (LIST 'LIST* ''ARRAYCALL (LIST 'QUOTE TYPE) (LIST 'QUOTE LONG) 'INDEXLIST)) ゆえに、ABBAは以下と同等である。 (DEFMACRO ABBA (SHORT LONG TYPE) (LIST 'DEFMACRO SHORT '(&REST INDEXLIST) (LIST 'LIST* ''ARRAYCALL (LIST 'QUOTE TYPE) (LIST 'QUOTE LONG) 'INDEXLIST))) しかし、これは、バッククォートを用いるバージョンよりもずっと読みづらい。 ネストされるバッククォートのこれ以上の例は、[Steele, 1990c]のAppendix Cを参照のこと。 バッククォートとDEFMACROは大きな違いをもたらした。標準的な形式で利用 可能になった、表現力におけるこの飛躍は、実験的な方言が共有され得るよう に標準的な移植可能な方法で新たな言語構造を定義することがこの時ずっと容 易になったので、言語拡張の新たなうねりをし始めた。David Moonを含む何人 かは、言語設計者の道具としてのLispの成功は、ユーザがプログラム表現とし ての言語とリストの構造を処理するものとしてLispを用いるマクロを定義する ことができ、言語のシンタックスとセマンティックスを容易に拡張できること に大きく依っていると述べた。1980年、Kent Pitmanは、新たな言語シンタッ クスを定義する中で、FEXPRに対するマクロの優位に関する非常に良い要約を 書いた[Pitman, 1980]。 しかし、それぞれのマクロが、この新たなフォーマットで表現することが容 易というわけではなかった。上で議論したINCを考えてみよう。1978年11月当 時、Lisp MachineのDEFMACROの分配は、"付加"引数形式を扱うほど豊かではな かった: (DEFUN INC MACRO (VAR . REST) `(SETQ ,VAR (+ ,VAR ,(IF REST (CAR REST) 1)))) 付加的な部分は、明示的にプログラムされた条件式で扱われなければならない (ここではIFを用いて表現されている。IF自身も、おそらくSchemeの影響下で、 同等のCONDフォームへ展開するマクロとしてLisp-Machine Lispで導入された)。 この欠陥はすぐに発見され、DEFMACROがDEFUNと同じ複雑なラムダリストシン タックスを受けいられるようにすることで素早く改善された: (DEFUN INC MACRO (VAR &OPTIONAL (N 1)) `(SETQ ,VAR (+ ,VAR ,N))) Lisp Archiveによると、このことが起きたのは1979年1月であり、その頃に MacLispは、Lisp-Machine Lispから&キーワードつきのDEFMACROとDEFUNを採り 入れた。 付加的な問題は、Kleene starを伴う拡張BNFで表現されるような種類の繰り 返しのシンタックスが、このフレームワークではとらえられず、明示的にプロ グラムされなければならないことだった。この単純なLETの定義をじっくり考 えよう: (defmacro let (bindings . body) `((lambda ,@(mapcar #'car bindings) ,@body) ,@(mapcar #'cadr bindings))) 束縛の繰り返し処理に対してMAPCARを使っていることに注意しよう。この困難 は、Lisp-Machine LispあるいはCommon Lispによっては取り組まれなかった; そのコミュニティでは、&キーワードつきのDEFMACROは今日の最先端である。 しかし、Common Lispは、そのようなラムダリストの再帰的なネストを許すよ うに、DEFMACROを一般化した。 Lispマクロを理論と実践でさらに発達させることは、主にSchemeコミュニティ で進展した。そのコミュニティはスコーピングの問題に関心をもっていた。マ クロは、スペシャル変数がもっていたスコーピングの問題や偶然の名前捕捉と 同じ種類の危険をはらんでいる。1963年のHartの時代から1980年代中頃までの Lispマクロに伴う問題は、マクロ呼び出しは、セマンティックスを伴わないシ ンボルで構成される式へ展開することである。プログラムの中で再び置換され るとき、マクロ展開は、局所環境によってはおそらく非常に驚くべき意味を持 ち得るかもしれない(他の言語のマクロ - Cのプリプロセッサ[Kernighan, 1978; Harbison, 1991]はその一例 - も、テキストまたはトークンのまっすぐ な置換によって動作する場合は同じ問題をもつ)。 このような問題を避けるための一つの実際的な方法は、%%foo%%のような奇 妙な名前を選ぶか(しかし、偉大なる知性がなんとしばしば同様の名前を考え るかのかは驚くべきことである)、(上で示したselectの例の中でHartが行なっ たように)gensymを使うか、名前の衝突を防ぐために複数のobarrayまたはパッ ケージを使うかのいずれかによって、ユーザが偶然出会いそうにない名前をマ クロ作者が選ぼうとすることである。しかし、これらのテクニックのいずれも、 完全な(iron-glad)保証は提供しない。Steeleは、thunkを注意深く使うことが その問題を取り除くと立証できるだろうが、すべての状況でではないと指摘し た[Steele, 1978a]。 Schemeの支持者たちは、これらの準備のすべては、Schemeに"公式に"採用す るには欠陥が多すぎるか、あまりに汚いと考えた。その結果、Schemeは1980年 代に多様化した。ほぼ全ての実装がある種のマクロ機構をもったが、どの2つ として似たものはなかった。ほとんど全ての人が、マクロ機構は原理的にも実 践的にも非常に貴重だが、それぞれの特定の実例は一種の家庭の秘密のような ものとして軽蔑されていることに同意していた。正しいこと(The Right Thing)さえ見つかれば! この問題は、Schemeの標準を開発する可能性に関す る噂が流布されるにつれて、さらに緊急になった。 1980年代中頃、2つの新たな種類の案が提唱された: 衛生的マクロ(hygienic macros)と文法的クロージャ(syntactic closures)である。どちらのアプロー チも、参照が定義へ正しくマッチすることを確実にするために、特別な文法環 境の使用を伴う。関連する系列の仕事は、エクスパンダ関数を明示的に渡して 操作することで、プログラマが展開プロセスを制御できるようにする[Dybvig, 1986]。これらの全てはSchemeのためのマクロ機構として意図された。以前の 方法は、その他の点ではこれほどエレガントな言語に採用するにはあまりにひ どく欠陥があるとみなされたのである。 衛生的マクロは、Daniel Friedman, Matthias Felleisen, そしてBruce Dubaの助力の元で、Eugene Kohlbeckerによって1986年に開発された [Kohlbecker, 1986a]。そのアイディアは、元のソースコードに現れていたの か、あるいはマクロ展開の結果として導入されたのかを示すタグを変数の出現 にラベル付けすることである; 複数のマクロ展開が生じる場合、そのタグは、 どの展開ステップと関係していたかを示さなければならない。そのテクニック は、変数参照が異なるステップで導入された束縛を参照できないように、変数 の名前を変える。 Kohlbeckerの博士論文[Kohlbecker, 1986b]は、マクロ定義のためのパター ンマッチングとテンプレート置換言語を提案することで、これをさらに一歩先 へ進めた; 下にあるメカニズムは、名前の衝突を防ぐために、衛生的マクロ展 開を自動的に用いた。そのマクロ定義言語は、広範囲の有用なマクロを表現す るために十分に豊かだったが、ユーザが指定した任意のLispコードを実行する 機構は提供しなかった; この制限は、よい衛生の保証を破壊することを防ぐた めに必要と考えられた。この小さな言語は、それ自身が興味深い。(その間で 任意の計算を行なう機会をもつ)DEFMACROとバッククォートの独立したマッチ ングや置換の機構ほどの一般性がない一方で、BNFのような記法を用いること で選択的で反復的なフォームを、複数の生成を許しマッチする最初のものを用 いることで選択的な状況を考慮している。たとえば、INCは以下のように定義 されるだろうし、 (extend-syntax (inc) () ((inc x) (inc x 1)) ((inc x n) (setq x (+ x n)))) LETは以下のように定義されるだろう。 (extend-syntax (let) () ((let ((var value) ...) body ...) ((lambda (var ...) body ...) value ...))) 省略記号"..."は、一種のKleene starとしての役目をする。展開の中で、変数 と値のペアが暗黙に分配され、2つの別のリストに再構成されるやりかたに注 目しよう。 extend-syntaxへ与えられる最初のリストは、マクロシンタックスの一部で あるキーワードのリストであり、変数参照の可能性があるものとしてはタグ付 けされない。2番目のリストは、マクロ展開によって導入されるかもしれない が、引数フォームと相互作用するように意図されている変数に言及する。たと えば、Dahlの作[Knuth, 1974]だとされるn+1/2ループを(Schemeの call-with-current-continuationプリミティブを用いて)僅かに一般化した実 装を考えよう; (もしあれば)while節が失敗するか、exitが使われるまで、文 を繰り返し実行する。 (extend-syntax (loop while repeat) (exit) ((loop e1 e2 ... repeat) (call/cc (lambda (exit) ((label foo (lambda () e1 e2 ... (foo))))))) ((loop e1 ... while p e2 ... repeat) (call/cc (lambda (exit) ((label foo (lambda () e1 ... (unless p (exit #f)) e2 ... (foo)))))))) この例では、loop, while, そしてrepeatはキーワードであり、変数参照の可 能性があるものと混同すべきではない; exitはマクロによって束縛されるが、 マクロ呼び出しの引数フォームの中で使われることを意図している。名前foo はそのような使用を意図してはおらず、衛生的マクロエクスパンダは、名前の 衝突を避けるために必要な場合はその名前を変えるだろう(ある名前を使用可 能にするためには苦労しなければならないことに注意しよう; デフォルトはそ れを安全にしておくことであり、そのことが初心者のマクロ作者が extend-syntaxを使うことをより易しく安全にしている)。while節がない場合 に少なくとも1つのフォームが存在することを必要とするために、イディオム "e1 e2 ..."を使っていることに注意しよう。 文法的クロージャは、Alan BawdenとJonathan Reesによって1988年に提案さ れた[Bawden, 1988]。彼らのアイディアは、Dybvig, Friedman, そしてHaynes の展開渡しのテクニック[Dybvig, 1986]に強い類似性をもっているが、より一 般的である。文法的コンテキストは、衛生的マクロ展開の自動的に管理された タグによってではなく、環境オブジェクトによって表現される; そのような文 法環境に関してコード片を"閉じ"てもよく、それによって、マクロ作者に、あ るシンボルと別のシンボルの出現の間の対応の明示的な制御を与える。文法的 クロージャは、大きな力と柔軟性を提供するが、正しく使うという重荷をプロ グラマに課す。 1990年、(以前インディアナ大学にいた)William Clingerが、衛生的マクロ と文法的クロージャの利点を結合し、二次ではなく一次の時間で実行する利点 を加えた大統一を提案するために、Reesと協力した。それらのテクニックは、 十分に適切なことに、"動作するマクロ(macros that work)"と呼ばれた [Clinger, 1991]。キーとなる洞察は、ラムダ算法での還元(reduction)への類 推によって説明されるかもしれない。しばしば、α変換のルールは、それに続 くβ還元が名前衝突を生じないようにラムダ算法式の中の変数の名前を変える ために適用されなければならない。このような名前変更を全て一度に行なうこ とはできない; 名前変更にβ還元を点在させる必要があるが、それは、β還元 はラムダ式のコピーを2つ作ることができ(ゆえに両方が同じ名前を束縛する)、 一方の束縛が他方の束縛へ衝突をもたらすからである。同じことはマクロでも 言える: 名前変更をマクロ展開に点在させる必要がある。ClingerとReesの貢 献は、この問題を明らかにし、速く完全な解決法を提供したことだった。 Scheme標準[IEEE, 1991]は、マクロ機構なしで採用されたので、この時点で は、まだ混乱が公式に支配している。マクロは、現在でも活発な研究トピック であり続けている。 Lispプログラマにとって、なぜマクロはそんなに重要なのか? 単にマクロが 提供するシンタックス上の便利さのためではなく、マクロはプログラムを操作 するプログラムであり、そのことは常にLispコミュニティの中心的テーマであ り続けているからである。FORTRANが数を、Cが文字とポインタをこき使う言語 であるなら、Lispは、プログラムをこき使う言語である。そのデータ構造は、 プログラムテキストを表現や操作するために有用である。マクロは、メタ言語 で書かれたプログラムの最も直接の例である。Lispはそれ自身のメタ言語であ るので、プログラミング言語全体の力が、プログラムテキストを変形する仕事 を行なうために用いられ得る。 比べると、Cのプリプロセッサは完全に無気力である; そのマクロ言語は、 もっぱら置換とトークン連結からできている。条件式があり、条件によってマ クロを定義してよいが、Cのマクロは、そのような条件式に展開することはで きない。再帰もメタ再帰もなく、それは、Cのマクロは自分自身を呼び出すこ とも他のマクロを定義することもできないということである。Lispユーザは、 これはばかげていると感じる。彼らは、記述や計算の目的と同じように、プロ グラミングのプロセスに非常に大きな関心があり、この目的のために可能な限 り最良の表現手段をもつことを要求するのである。なぜ完全なプログラミング 言語自身よりも劣った何かで手をうつのか? 3.4 数に関する機能 Lisp 1.6からPDP-6 Lispまで、多くのLispシステムは、少なくとも1語の fixnums(整数)と1語のflonums(浮動小数点数)を提供した(PDP-1 Lisp [Deutsch, 1985]はfixnumsだけをもっていた; 明らかにM-460 Lisp [Hart, 1985]でも同じだった。7090上のLisp 1.5は、Q-32 Lisp [Saunders, 1985b]や PDP-6 Lisp [PDP-6 Lisp, 1967]のように浮動小数点数をもっていた [McCarthy, 1962])。 bignums(任意の大きさの整数値を表現できるように可変量の記憶域を用いる データタイプであり、bignumsが格納される場所であるヒープの合計サイズに 従う)の起源については、まだ少し不確かである。MacLispとStanford Lisp 1.6にほぼ同じ時期に、そしておそらくStandard Lispにも現れたようである。 それらは、REDUCE [Hearn, 1971]やMACSYMA [Mathlab Group, 1977]のような 記号代数プログラムのために必要だった。今日では、bignumsを扱うことは、 無条件に要求されているわけではないが、Lispの特徴的な機能の1つである。 Scheme標準[IEEE, 1991]とCommon Lisp [Steele, 1990c]は、どちらもそれら を必須としている。通常は、Knuthの第2巻に詳述されているアルゴリズムが使 われる[Knuth, 1969; Knuth, 1981]。Jon L Whiteは、全ての事柄をアセンブ リ言語でコード化する代わりに、多くのbignum算術をLispで効率よくコード化 できるようにするプリミティブの集合に関する論文を書いた[White, 1986]。 BIGFLOAT算術に関する文献もあった。それは記号代数システムで使われてき たが[Mathlab Group, 1977]、Lisp方言の定着物にはならなかった。bignumsを 持てばそこへの道の2/3まで来ているので、Lispは、この種の研究のためのプ ラットフォームとしてしばしば使われる[Boehm, 1986; Vuillemin, 1988]。 MacLispの関数HAULONGとHAIPARTは、Macsymaのbigfloat算術をサポートするた めに導入された; これらは、Common Lisp関数INTEGER-LENGTHと(Lisp-Machine Lispを経由して)LDBになった。 1980年代に、Common Lispの開発者たちは、IEEE浮動小数点標準[IEEE, 1985]の導入に取り組んだ(この執筆までに、多くの他の高水準プログラミング 言語はIEEE浮動小数点標準に真剣に取り組んでこなかったことは注目に値する。 実際、ANSI X3J3 (FORTRAN)は、そのようにせよという明示的な要求を拒絶し た)。 Lispは算術的なプログラミング言語としては通常考えられていない一方で、 その方向に3つの強い影響があった: MACSYMA, S-1プロジェクト, そして Gerald Sussmanである。 最初の良い算術Lispコンパイラは、MACSYMAグループのために開発された [Golden, 1970; Steele, 1977c; Steele, 1977e]; 算術のコードが速くてコン パクトであることは、彼らや彼らのユーザにとって重要だった。その成果は、 DEC PDP-10 FORTRANコンパイラと競争するLispコンパイラだった[Fateman, 1973]。 当初、S-1は、速い信号処理機になるように意図されていた。想定されてい た応用の一つは潜水艦の発見であり、それは数値信号処理と人工知能テクニッ クの混合を必要とすると思われていた。そのプロジェクトは、浮動小数点数算 術の設計にW. Kahanのアドバイスを受けたので、やがてIEEE標準になるものに きわめて類似することになった。S-1 Lispの良い算術コードを生み出すために、 MacLispコンパイラのテクニックを改良することは適切に思われた[Brooks, 1982b]。S-1は、4つの異なる浮動小数点フォーマット(18, 36, 72, そして144 ビット)を提供した[Correll, 1979]。S-1 Lispに影響されて、Common Lispは、 そのようなアーキテクチャ上のバリエーションを収容するために、浮動小数点 データ型の拡張されたシステムを提供する。 Common Lispが複素数を含んでいるのも、S-1から継承されたことだった†1。 これは、Scott Fahlmanが相当こだわった点だった。流行ったジョークの一つ として、Guy Steeleによって開発された、初期のCommon Lisp実装に対する受 容テストがあった。それは3つの部分からできていた。最初にTとタイプする; Tと応答すればパート1はパスである。 次に、階乗(factorial)関数を定義して、以下を計算する; (/ (factorial 1000) (factorial 999)) 1000を戻せば、パート2はパスである。3番目に、(atanh -2)を試す。複素数を 戻せばパスである; 正しい複素数を戻せば特別の称賛を得られる。あらゆる Common Lisp実装が第3パートをパスするまでには長い時間がかかった。Steele は、この3つの部分のテストを使って、見本市の会場で1つか2つの実装を壊し た。 Gerald Sussmanと(Gerald RoylanceやMatthew Halfantを含む)彼の学生は、 算術アプリケーションと、算術プログラムを生成および変形するためにLispを 用いることに興味をもち始めた[Sussman, 1988; Roylance, 1988]。また、 Sussmanは、MITで学部生へLispを教えることにかなりの時間を費やした。10.0 と4.0の商は2.5だが10と4の商は2であると学生に話さなければならないのは、 完全にどうかしているとSussmanは考えた。もちろん、ほとんど全ての他のプ ログラミング言語が同じ問題をもっているが(Pascal [Jensen, 1974]と、その 派生物は特筆すべき例外である)、それは言い訳にはならない; Lispはもっと 良いものを求め、そして、数学の慣例の数世紀は、コンピュータの分野での一 時的な逸脱の数十年よりも重い。Sussmanの勧めで、/関数は必要なら有理数を 戻すように定義されたので、Common Lispでは(/ 10 4)は5/2を生じる(これは、 言語への急進的な変更とはみなされなかった。有理数はすでに記号代数システ ムで使われていた。いずれにせよ、Common Lispの開発者たちは、クライアン トから頻繁に要求される言語機能に単に統合しようとしていた)。 これらの全ては別の論争を引き起こした。MacLispやその子孫では、スラッ シュは文字引用符(character quoter)だったからである; さらに、バックスラッ シュが剰余オペレータ(remainder operator)だった。最終的に、委員会はスラッ シュとバックスラッシュの役割を交換することを決定し、その結果、スラッシュ はアルファベットに、バックスラッシュは文字引用符になり、除算操作が"//" ではなく"/"として、有理数が慣習的な記法として書かれるようになった。ま た、このことは、そのころあまり知られておらず(Lispコミュニティでは)あま り愛されていなかったUnixと呼ばれるオペレーティングシステムによって引き 起こされたいくつかの問題も解決した。Unixは、文字引用符としてバックスラッ シュを、ファイル名としてスラッシュを用いていたのである。しかし、それは、 MacLispやZetalispからの主要な非互換性であり、Common Lispをかなりの批判 を免れない状態にした。 もちろん、このことはCommon Lispを、場合によっては有用な切り捨ての整 数除算操作がない状態にした。S-1の多くの丸めのモード[Correll, 1979; Hailpern, 1979] (それはKahanに影響を受けた)に触発されて、Steeleは、 Common Lispに4つのバージョンの整数除算操作を加えた - それらはtruncate, round, ceiling, そしてfloorであり、それぞれは1つか2つの引数を受け取り、 商と剰余を戻す - したがって、Pascalをすらしのいだのである。全体的には、 Common Lispは、FORTRANがかつてそうだったよりも、ずっと豊かな算術プリミ ティブの集合を提供し、複素三角関数の分岐切断線のような詳細にすらもっと 注意を払っている。 浮動小数点数の印字には問題がある。Jon L Whiteは、1970年代初頭から始 めて、何年もその問題を追求した。Guy Steeleは、1980年代初めにLispコミュ ニティで非公式に流布し、少なくとも1つのPascalの実装で使われたそのアプ ローチと解決法を定式化した。Steeleは、それを完成することをさらに何年も ためらった。それは、1990年にようやく発表された[Steele, 1990b] (そのこ ろまでに、Kent Dybvigがそのアルゴリズムをさらに改良した)。愉快な偶然に よって、William Clingerが対応する入力の問題の解決に着手し、彼の解決法 を同じ会議へ提出したので[Clinger, 1990]、それらは一緒に出版された。 関連する記録として、Steeleは、1974年にMacLispへ、ローマ数字のI/Oをハッ クとして加えた。制御変数BASEとIBASEは、以前は2から36までの整数値に制限 されていたが、独立してROMANへも設定され得るようになった。この機能は多 少危険なものだった: 以下のようなコードを読む場合、 (do ((i 0 (+ i 1)) (x '() (cons (sqrt i) x))) ((= i 20) (return x))) (setq ibase 'roman)の後では、以下と同様のものを生じた。 (do ((1 0 (+ 1 1)) (10 '() (cons (sqrt 1) 10))) ((= 1 20) (return 10))) この機能の当初の発表では、値ROMANがローマ数字のI/Oになるだけではなく、 BASEまたはIBASEをCUNEIFORMに設定でき、すると、あなたのLispは楔形になる だろうと記述した。そのころから、ローマ数字のI/Oはちょっとした古典的な ハックになり、Zetalispの、そして後にはCommon Lispの関数FORMATの一部に なった。 †1 1970年代の終わりに、PDP-10のMacLispに倍精度数と複素数をインスト ールする計画があったが、そのプロジェクトは完成しなかった。Steeleはそれ に対するデザインを行なったが、その後それを忘れてしまった。結局、 Sussmanを指導教授とする学部生であるBarbara Kernsが、そのプロジェクトを 引き受けた。Steeleは、関連するデザインの文書や背景となる材料を彼女に与 え、ある思いがけない不運のために、彼女は次の日にそれらを紛失してしまっ た。困った彼女は、彼女の学科の仕事に没入し、その後の4ヶ月をSteeleを避 けて過ごした。彼は、自身のプロジェクトに没入し、彼女がいないことを特に 気にしなかった。次の年に彼らは結婚した(彼らは最初の記念日をスタンフォ ードの学生寮で、1980 Lisp Conferenceでのそれぞれの講演のためのOHPを準 備して過ごした。おお、若きかな!)。 3.5 オブジェクト指向プログラミング [以下のテキストは非常に不完全であり、書き入れられる必要がある。] OOPとLispの最初の融合は、メッセージパッシングに基づく拡張だった。た とえば、GreenblattまたはHoward Cannonは、1974年か1975年にPARCを訪れ、 Lisp machine Lispのための単純なメッセージパッシングシステムを実装した。 後に、Cannonが多重継承を加え、最初のFlavorsが誕生した[?]。 それより前に、Actors [?]やPlasma [?]が、メッセージパッシングと並行性 を探求した。Scheme [Sussman, 1975b]は、Actorsを理解するための試みだっ た。クロージャとアクタは同じものだと考えられた。おそらく、Actorsは Simula (Simula IとSimula67 [?])に触発された。 FlavorsはSmalltalk [?] [?] [?] [?] [?]から来た。 Flavors [?] [?; ?]は多重継承をもつ(Smalltalkには多重継承において初期 の試みがあったが、それは、私が考えるには、コピーシステム(copying system)であり、追加のライブラリとして構築された)。Flavorsは1970年代の 終わりにメソッド結合を導入したが、それは、mixinを定義することの自然な 結果である。Flavorsは自動的な線形化メカニズムを用いるが、その代替物は カプセル化(明示的な命名)と選択である[?; ?; ?; ?] [?]。LOOPSは、 Smalltalkから派生した、Interlispに基づくOOPである[?]。それは、単一継承 とメッセージパッシングをもっていた。 CommonLoops [Bobrow, 1986]はLOOPSの派生物であるが、クラス所有権の記 法を少し拡張している。また、New Flavors [Moon, 1986] [?]からも取り入れ た。 Common Objectsは、カプセル化に基づくOOPシステムである[?]。そのカプセ ル化の機能は、CLU [?]でのカプセル化の機能といくらか類似性がある。 Object Lispは、委譲に基づく言語である[Drescher, 1987], [?], [?; ?]。 Common Lisp Object Systemは、CommonLoopsとNew Flavorsを慎重に混合し たものである。それは、真の総称関数を導入し、多態オブジェクト指向言語上 のSmalltalkの影響の残りを一掃した[?; ?], [Steele, 1990c], [?]。 それは、CLOS自体をカスタマイズ/変更するために特定化され得るオブジェ クト指向プログラムとして扱う、メタオブジェクトプロトコルを導入した[?] [?; ?; ?] [?]。 Schemeでは、オブジェクト指向に関するいくつかの試みがあった。これらは、 SCOOPS [?], OakLisp [?; ?], John UlrichによるSemantic Microsystems(あ るいは現在の呼び名ではLightship)のための委譲言語だった[?]。AdamsとRees [?]も参照のこと。ヨーロッパには、Cointe [?], EuLisp [Padget, 1986; ?] がある。 [スケッチの節の終わり。] 3.6 並列Lisp [以下のテキストは非常に不完全であり、書き入れられる必要がある。] これらは主なものである: Qlisp [Gabriel, 1984] [Goldman, 1988], MultiLisp [Halstead, 1984] [?], MultiScheme [?] [?]。Qlispの命題パラメ ータへの改良[?]。 [?], [?] [?]のようなもっと理論的なものもある。 Lindaの影響を受けたもの[?]。SPUR [?], Curare [?]がある。自動的な並列 化がある[?; ?]。 [スケッチの節の終わり。] 3.7 いくつかの著しい失敗 他のプログラミング言語とLispコミュニティ内での実験の両方から、長期にわ たって新たな機能を吸収しようとするLispの傾向にもかかわらず、様々な形式 で何度も試みられたが何らかの理由のためにLispコミュニティでは全く流行ら ない、いくつかのアイディアがある。これらのアイディアの間で有名なものに は、Algolスタイルのシンタックス、一般化された多値、そして、変数のユニ フィケーションを伴う論理プログラミングである。 3.7.1 Algolスタイルのシンタックス Steve RussellがEVALの実装を最初に手でコード化して以来、S式がプログラム を書くための標準的な記法だった。ここ30年のほとんどあらゆるLispシステム では、だいたい以下のような形式で(要素のリストとして表現される2つの集合 の和集合を計算する)関数UNIONを書けるだろう: (defun union (x y) (cond ((null x) y) ((member (car x) y) (union (cdr x) y)) (t (cons (car x) (union (cdr x) y))))) しかし、Lispの設計での元々の意図は、プログラムはM式として書かれるだ ろうというものだった; S式のシンタックスは、データの表現のためにだけ意 図された。M式の記法のUNION関数は、以下のように見える: union[x;y] = [null[x]→y; member[car[x];y]→union[cdr[x];y]; T→cons[car[x];union[cdr[x];y]]] しかし、McCarthyが注記したように[McCarthy, 1981]: 予期しないインタプリタの出現が言語の形式を凍結する傾向があった… M式を定義するプロジェクトはまさに…完成も完全に捨てられることも なかった。それは単に不定の未来へ後退し、考案され得るあらゆる FortranやAlgolのような記法よりも内部的な記法(すなわち、S式である) を好む新世代のプログラマが現れた。 まだ、これが話の終わりではなかった。そのときから、LispにAlgolのような シンタックスを提供するために、多くのその他の努力がなされた。再三再四、 Lispのユーザまたは実装者は、言語の中に欠落を感じ、そして解決法を提供し てきた - そしてかなりのユーザのグループを引き付けることも稀ではなかっ た - そして、結局は、それらのどれもいまだに受容を獲得していない。 この最も初期の例 - もちろん、M式の後で - は、HennemanのA言語だったよ うである[Henneman, 1985]。Hennemanは、以下のUNIONの定義を与える: (DEFINE UNION (OF AND) (8) (UNION OF X AND Y) (IF X IS EMPTY THEN Y ELSE IF FIRST OF X IS A MEMBER OF Y THEN UNION OF REST OF X AND Y ELSE CONNECT FIRST OF X TO BEGIN UNION OF REST OF X AND Y END)) この定義の中の数8は、UNIONオペレータの優先度である; 挿入句的なデリミタ としてのBEGINとENDの使用に注意しよう。CONNECT . . . TO . . .オペレータ (CONSを意味する)がより高い優先度をもつので必要なのである。 我々は、Hennemanが、彼の論文ではM式やS式をわざわざプリティプリントし ているのに、彼の同時代のS式でしばしば見られる一種の追い込みの、ブロッ クパラグラフのスタイルで彼のA言語の全ての例を示したことを不思議に感じ る。今日では、我々は、このようなプログラムを、明快さのためにこのように フォーマットするだろう: (DEFINE UNION (OF AND) (8) (UNION OF X AND Y) (IF X IS EMPTY THEN Y ELSE IF FIRST OF X IS A MEMBER OF Y THEN UNION OF REST OF X AND Y ELSE CONNECT FIRST OF X TO BEGIN UNION OF REST OF X AND Y END )) そのようなフォーマッティングは弁明を許されなかった; 当時のAlgolプログ ラマは、公表されたプログラムの中で類似のインデンテーション規約を用いて いた。 [以下のテキストは非常に不完全であり、書き入れられる必要がある。] Lisp 2.0 [スケッチの節の終わり。] EL1言語は、Ben Wegbreitによって、彼の博士課程の研究の一部として設計 された[Wegbreit, 1970]。それは、大まかにはAlgolのような表面のシンタッ クスと強いデータの型付けをもつLispとして特徴づけられるかもしれない。 ECLと呼ばれる完全なプログラミングシステムが、1970年代の初めにハーバー ド大学でEL1の周りに構築された[Wegbreit, 1971; Wegbreit, 1972; Wegbreit, 1974]。EL1のUNION関数はこのように見える: union <- EXPR(x: FORM, y: FORM; FORM) [) x=NIL => y; MEMBER(CAR(x), y) => union(CDR(x), y); CONS(CAR(X), union(CDR(x), y)) (]; x, yの型宣言と、型FORM(ドットペアへのポインタ)としての結果に注意しよう。 二重音字[)と(]は、BEGINとENDに等しい(それらは、Model 33 Teletype上では、 ここで見えるよりももっとよく見えた)。ブロックの中では、矢印=>は、その ブロックからの条件付きの値戻しを示し、結果として、McCarthyのM式のため の条件式の記法を思い起こさせるものになっている。Lisp自体は、その頃のハ ーバード大学の計算機科学技術研究センターでは広く用いられてはいなかった; EL1やPPL(Polymorphic Programming Language, いくぶんJossのような対話的 なシステム)が、その頃のLispに対するハーバード大学の回答だったのかもし れない。ECLは、Wegbreitがプロジェクトの途中でハーバード大学を離れて Xeroxに行かなければ、もう少し長く生き残ったかもしれない。以上のように、 ECLは、ハーバード大学での研究や教育課程の仕事のために1970年代を通して 使われた。 TeitelmanのCLISP (Conversational Lisp)についてはすでに議論したが、そ れはInterlispの一部だった[Teitelman, 1974]。関数UNIONはInterlispに組み 込まれたが、CLISPを用いてこのように定義され得ただろう: DEFINEQ((UNION (LAMBDA (X Y) (IF ~X THEN Y ELSEIF X:1 MEMBER Y THEN UNION X::1 Y ELSE ] CLISPでは、NOTまたはNULLを表す~は単項オペレータである。X:nはリストXの 要素nであるので、X:1は(CAR X)を意味する; 同様に、X::1は(CDR X)を意味す る。関数MEMBERは、中置オペレータになるようにCLISPによって事前に定義さ れているが、UNIONはそうではない(しかし、望むならユーザがそのように定義 できる)。かぎ括弧は、リストの構築を表す; そのようなリストの中の!は繋ぐ ことを表すので、は(CONS A B)を意味する。最後に、必要な数の閉じ括 弧(この場合は4)を表すための最後の]の使用は、CLISP固有の機能ではないが、 Interlispのスタイルと一致している。 MLISPは、LispのためのAlgolに似ているシンタックスであり、Horace Enea によってIBM 360のために最初に実装され、Stanford Lisp 1.6の元でPDP-10の ために後に再実装された[Smith, 1970]。それは、中置オペレータ; 繰り返し のための複雑なFOR構文; A(1,3) (二次元配列の要素)やL[1,3,2] ((cadr (caddr (car L)))と同等)のような様々な下付き文字の記法; "ベクタ" 操作 (MAPCARのための簡潔な記法); そして、分配代入を提供した。 EXPR UNION (X,Y); %MLISP version of UNION IF ¬X THEN Y ELSE IF X[1] ε Y THEN UNION(X↓1,Y) ELSE X[1] CONS UNION(X↓1,Y); Vaughan Prattは、CGOLと呼ばれるLispのためのAlgolスタイルの記法を開発 した[Pratt, 1973]。S式の中に代数の文法を埋め込むのではなく、CGOLは、別 の本格的なトークナイザとパーサを用いた。これは、Prattがスタンフォード にいた1970年にStanford Lisp 1.6のために最初に実装された; この頃、MLISP プロジェクトとのアイディアの交換があった。PrattはMITに行った直後に、 MacLispのためのバージョンを実装した[Pratt, 1976]。このパーサのバージョ ンは、IBM Yorktownで記号代数システムSCRATCHPADや、MITのProject MACで MACSYMAの中でも使われた; Fred Blairは、彼はLISP370も開発したのだが、 SCRATCHPADに対する再実装を行ない、Michael GeneserethはMACSYMAに対して それを行なった。 我々のUNION関数のCGOLバージョンは、中置オペレータとしてそれを定義す る(数14と13は、パーサに対する左と右の"結合力"である): define x "UNION" y, 14, 13; if not x then y else if member(car x, y) then cdr x union y else car x . cdr x union y ◇ ここでは、MITで実装されたCGOLのバージョンを仮定しているが、それは標準 ASCII文字集合を守っていた; スタンフォードの拡張文字集合を用いる全く同 じ定義は以下のようになるだろう: define x "∪" y, 14, 13; if ¬x then y else if αx ε y then βx ∪ y else αx . βx ∪ y ◇ "."は、上の例の両方でCONSを表す; デリミタ◇(実際はASCIIの"altmode"文字 であり、今日では"エスケープ"と呼ばれている)は、トップレベルの式の終わ りを表す。全ての単項Lisp関数は、CGOLでは単項オペレーションであり、それ はCARやCDRも含む。上の定義では、このような単項オペレーションはとても高 い優先度をもつので、cdr x union yは(cdr x) union yを意味するのであって、 cdr (x union y)を意味するのではないという事実に頼っていた。また、最後 の式が(car x) . ((cdr x) union y))としてパースされるように、"."に対す るUNIONの結合力を注意深く選んだ。これが最良の選択であることは明白では ない; Hennemanは、UNIONより高い優先度を(CONNECT ... TO ...のフォームの 中で)CONSに与えることを選んだ。Prattは述べた[Pratt, 1976]: CGOL記法を使いたいが、結合力とは関わりたくない場合、Lispで書い ているかのように、それぞれのCGOLの式を括弧で囲めばよい。しかし、 全ての括弧を省略しても…それほどしばしばおかしくはならないだろう。 Hennemanの意見とこれを比較しよう[Henneman, 1985]: 実際に得られる不正な結果の多くの一つの大きな原因は、関数に割り 当てられている不正な優先度である。 1970年代の間、多くの"AI言語"が、特定のプログラミング構造物を提供する ために設計され、それから、AIアプリケーションのためのプログラムを書くこ との助けになるように考えられた。これらのいくつかはLispの中に組み込まれ、 したがって、Lispのシンタックスを単に継承した(そして、いくつかの場合に は、Lispのシンタックスに影響を与えた - これらの議論については4節を参照)。 それらの中で組み込まれなかったものは、通常はAlgolのそれに関連するシン タックスをもっていた一方、(記号データ構造や再帰関数のような)Lispの他の 機能のいくつかを含んでいた。これらの中には、POP-2 [Burstall, 1971], SAIL [Feldman, 1972], そして、Pascalに基づくTELOS [Travis, 1977]があっ た。 LispにAlgolのようなシンタックスを導入するというアイディアは現れ続け、 普遍的なS式の使用は技術的な利点があると感じる(そして、算術式に対して広 く認められている相対的なS式の不格好さを気にしない)人々と、代数のシンタッ クスは、より簡潔であり、より便利であり、あるいは、より自然ですらある (それが何を意味しようと、これらの記法の全ては人工的であることを考慮し よう)と確信している人々の間での巨大な論争を作り出すことに滅多に失敗し ない。 我々は、Algolスタイルのシンタックスは、2つの理由でLispコミュニティ全 体としては実際には流行らなかったと推測する。第1に、行き渡るだけの十分 な特殊記号がない。記述の領域が数あるいは文字に限られているとき、それほ ど多くの関心があるオペレーションはなく、それぞれへ1つの特殊文字を割り 当てて済ませることは難しくない。しかし、Lispはずっと豊かな記述の領域を もっており、Lispプログラマは、言語設計でのさらにまた別の練習としてアプ リケーションにしばしば取り掛かる; そのスタイルは、新たなデータ構造や、 それらの上で動作する新たな関数を - おそらく数ダースあるいは数百 - 典型 的には必要とし、そんなに多くの別のシンボルを作り出すことは単純にたいへ ん困難である(APLコミュニティは確かにやろうとしたが)。結局、一般的な関 数呼び出しの記法に常に逆戻りするに違いない; それは、Lispプログラマが、 彼らが失敗するまで待たない、まさにそのものである。 第2に、そしておそらくもっと重要なことだが、Algolスタイルのシンタック スは、プログラムがそれらを表現するために用いられるデータ構造であるよう にはあまり見えないようにする。プログラムの表現を操作する能力が中心的な パラダイムである文化では、データとしてのその表現の見た目からプログラム の見た目を隔てる記法は、暖かく受け入れられそうにはない(そして、これは、 かつてそうであり、現在でもそうであるが、Common Lispの中にloopを含める ことに対する主な反対理由の一つである)。 他方で、Lispがプログラム表現とともに遊ぶことを容易にしているまさにそ のために、初心者が代替の記法で実験することは常に容易である。したがって、 我々は、将来のLispプログラマの世代が何度も何度もLispに対するAlgolスタ イルのシンタックスを再発明し続けることを予期し、彼らは、最初の夢中にな る期間の後、それを拒絶し続けるだろうということを同じく確信している(お そらく、このプロセスは、Lispハッカーのための通過儀礼だと考えられるだろ う)。 3.7.2 一般化された多値 Lispを拡張しようとする人の多くは、以下の道をそれぞれが独自に降りていっ た。ときには、関数から一つより多くのアイテムを戻すことが望ましい。グロ ーバル変数を通して結果のいくつかを戻すことは不様であり、それらがマシン レジスタで戻され得る、あるいはマシンの制御スタック上にプッシュされ得る ことが完全によくわかっているときに、結果のリストをコンスすること(シス テムが次のゴミ集めへずっと近くなるように押すこと)は非効率である。奇妙 にも、2つの結果を戻すことになっている関数の原型的な例は、記号的ではな く算術的である: 整数の除算は、商と剰余の両方を都合よく戻すだろう(実際 には、2つの別の関数を使うことは、プログラマにとってちょうど同じくらい 便利だろうが、我々は、一方の計算が他方をほとんどただ同然に生み出すこと を完全によく知っている - 再び言うと、これは効率上の問題である)。 それでは、何らかの基本的な多値を生成する手段が提供されているとしよう。 一つの方法は、新たな関数や特殊形式を導入することである。たとえば、 Common Lispは、Lisp Machine Lispにしたがって、VALUESと呼ばれる基本的な 関数をもっている; (values 3 4 5)の結果は、3つの数3, 4, そして5である。 以下の特殊形式は、 (multiple-value-bind (p q r) (foo) body) フォーム(foo)の値として戻された3つの値へ局所的に束縛された変数p, q, そ してrを用いて、その本体を実行する。 しかし、これは全てがとてもアドホックでありエレガントではない。おそら く、多値は言語自身の固有の構造から浮かび上がらされ得る。たとえば、ラム ダ式の本体が暗黙のVALUES構造であり、最後の部分フォームだけの値を戻す暗 黙のPROGNではなく、全ての部分フォームの値を戻すとしようか。それは、多 値を生成することの面倒をみる。さらに、関数呼び出しが、それぞれの部分フォ ームからの1つの値だけではなく、それぞれの部分フォームから戻される全て の値を使うように再定義されるとしようか。そうすれば、以下のように書くこ とができ、 ((lambda (quo rem) ...) (/ 44 6)) それによって、商7へquoを、剰余2へremを束縛する。それは、多値を消費する ことの面倒をみる。全てがとても単純できちんとしている! しまった、面倒を みるべき2つの細かいことがある。第1に、ラムダ式に戻ると、一貫性のために、 単にそれぞれの部分フォームの1つの値ではなく、全ての部分フォームの全て の値を戻す必要があることがわかる。だから、以下のフォームは、 ((lambda (quo rem) (/ quo rem) (/ rem quo)) (/ 44 6)) 4つの値を戻す: 3, 1, 0, そして2である。第2に、代入のような副作用をもつ 順に並んでいるフォームに対する必要性がまだある。単純な解決法は、 (setq x 0)や(print x)のようなフォームが値を戻さないようにすることであ り、したがって、 ((lambda (quo rem) (print quo) rem) (/ 44 6)) は、商7を印字した後に剰余2だけを戻す(これは、単に以下や、 (setq my-array (make-array 1000000)) このような対話的な初期化のステップのために、対話的なトップレベルが数百 行ものNILを次から次へと印字することの厄介を除去するので一石二鳥である)。 この全ては、たいへん単純で魅力的なスタックに基づく実装をもつ。プリミ ティブは、それらの値を全て、次々と、スタック上に単にプッシュする。関数 呼び出しに対する処理の開始時点で、スタック上にマークを置く; 全ての部分 フォームが処理された後に、最も新たなマークをスタックで単に探す; その上 にある全ては、関数呼び出しのための引数として使われるべきである - しか し、関数への制御を移す前にマークを確実に取り除くかキャンセルするかしな ければならない(代替の戦略は、マーカではなく浅く束縛されたカウンタを使 う; これは探索を回避するが、値がプッシュされるときにカウンタを更新する 費用がかかる)。ラムダ式の本体を処理することに対して、特別な行為が必要 とされないのは気持ちがよい。 なるほど、これは全てとてもきちんとしていてきれいである - そして、そ れを使おうとするとすぐに、保守担当者とコンパイラのどちらにとっても、コ ードを理解することがずっと、ずっと難しくなることがわかる。プログラマが、 以下のようなものを書かない自制心をもつ場合でさえ、 (cons (/ 44 6) (setq x 0)) これは、xを0へ設定した後で(7 . 2)を戻すのだが、コンパイラは、処理中の コードの中にこのような極悪なものが潜んでいないことをけっして確信できな い。どれだけ多くの値が、全てのユーザ定義の関数を含むそれぞれの関数によっ て生成されるかについてのかなり完全な情報がないと、コンパイラは、関数呼 び出しが正しい数の引数を供給するだろうということを確認できない。Lispの プログラミングエラーに対する一つの重要で実際的なチェックが、したがって ほとんど不可能にされる。 条件式は、さらに2つの問題を招く。第1に: (foo)が2つの値を戻す場合、以 下の解釈はどうなるだろうか? (if (foo) (bar)) 第2の値は捨てられるか、あるいは、第1の値が真なら戻される値として扱われ るか? おそらく、述語は、正確に1つの値を戻すことを必要とされるべきであ る。たいへんよろしいが、2つの部分フォームは異なる数の値を戻すかもしれ ないという事実が残っている; (if (foo) 3 (/ 44 6))は、単一の値3を戻すか もしれないし、多値7と2を戻すかもしれない。それは直ちに、どのコンパイラ も、一般にはどのくらい多くの値がそれぞれの関数呼び出しによって戻される かを推論できないということになる; それは、形式的には決定不能である。 さて、この全ては、弱く型付けされた言語であるLispの精神の中に完全にあ るように見えるかもしれない; 関数によって戻される値の型が実行時まで決定 できないかもしれないなら、まさにその数もそうであってはなぜいけないのか? それに、宣言が、ちょうど型宣言がすでに多くのLispコンパイラを助けている ように、効率が重要な場所では値の数を示すかもしれないではないか。それに もかかわらず、実際のところ、この道をたどったほとんど全ての人は、開発の この時点であきらめ、「この道は狂気に通じる」とつぶやきながら、タールの 沼に入らずに自宅に戻った。 我々自身は、独立してこの思考の道をたどり、同様にそれを行なったきわめ て少数の何人か他の人々と対話をもった。しかし、彼らの多くは、それについ て何かを発表する前に結局悪いアイディアだと判断し、まさにそのために、引 用できる発表された情報源はほとんどない(これは、実際に悪いアイディアで ある、あるいは、何らかの変形がその短所を除去できないと言っているわけで はない; ここでは、我々は、多くの独立した研究者たちの間の思考の類似性を 強調することを望んでいるだけである)。最終的に放棄される前に現実の実装 を生み出した最も注目に値する努力は、SEUSとPOP-2である[Burstall, 1971]。 SEUSの設計者と実装者(Richard Weyhrauch, Carolyn Talcott, David Posner, Ralph Goren, William Scherlis, Len Bosack, そしてGabriel)は、それは新 たな言語設計であり、速く、コンパイラとマイクロコードに基づく実装をもち、 プログラミング環境を完成したにもかかわらず、彼らの結果をけっして発表し なかった。POP-2は、AI言語として設計者によって考えられ、Lispの異種とし てではなく、1960年代終わりから1970年代初めにかけて作られた多くのAI言語 の一つだった; それは、ヨーロッパでかなりの人気を博し、論理プログラミン グ言語POPLOGを実装するために使われた[Mellish, 1984]。 3.7.3 論理プログラミングとユニフィケーション 1970年代から1980年代にかけて、単一の言語に、2つのおそらく主流のAIプロ グラミング言語族であるLispとPrologの利点を統合しようとする多くの試みが あった。そのような努力は、とりわけ日本の第5世代プロジェクトのソフトウェ ア面の特徴の一つだった。この例は、RobinsonのLOGLISP [Robinson, 1982]、 TAOプロジェクト[Takeuchi, 1983; Okuno, 1984]、そしてTABLOG [Malachi, 1984]である。関数型プログラミングとPrologを統合しようとする関連する試 みもあった(これらの全ては、KomorowskiのQLOG [Komorowski, 1982]やKahnと Carlssonの仕事[Kahn, 1984]で例証されるような、Prologを実装するための便 利な言語としてのLispの使用と対比されるべきだろう)。 このアイディアは、Prologで用いられる変数マッチングプロセスであるユニ フィケーションのために、Lispコミュニティでは流行らなかったと推測する。 実際、Lispの機能の多くをもつが手続き呼び出しの間はユニフィケーションを 用いる言語を容易に設計できる。問題は、ユニフィケーションは、結果として の言語がもはやLispだと全く感じられないほど、ラムダ束縛と本質的に非常に 異なることである。普通のLispプログラマにとって、それは、Prologの拡張だ がLispの拡張ではないように感じられる; 何か手続き呼び出しのように基本的 なものとして、単にそれだけをちょっとやってみることはできない。他方で、 Lispの手続き呼び出しをそのままにしておき、明示的に呼び出され得る別の機 構としてユニフィケーションを提供できる。しかし、そうなると、それは単に 別のLispライブラリルーチンであり、結果として、Prologのようには全く感じ られない。 3.8 その他のトピックス 有効に扱えるかもしれないその他のトピックスは: - 表現力豊かな機構としての継続 - 具体化(reification)とリフレクション - ゴミ集め(マーク/スイープを含むハイポイント、コピー、リファレンスカウ ントをもつflirtation、Bakerの実時間法[Baker, 1978]、とても大きなアド レス空間を扱うためのBishopの提案、Whiteの提案"それはやるな!" [White, 1980]、Moonの即時GC [Moon, 1984]; Brooksの普通のハードウェアのための GC; また、Computing SurveysでのCohenの論文にも言及しておく) - 効率的にスタックを管理するための様々なテクニック: スパゲッティスタッ ク[Bobrow, 1973], [Steele, 1977a]、McDermottのアイディア[McDermott, 1980]、SteeleとSussmanの遅延レジスタ保存[Steele, 1980]、数のスタック 割り当て[Steele, 1977e] [Brooks, 1982b]、Stallmanの幽霊スタック (phantom stacks)、GCはスタック割り当てよりも速いというAppelの主張 (Info. Proc. Letters 25, 275-279)、また[Clinger, 1988], [Bartley, 1986] [Hieb, 1990] - レコード構造、DEFSTRUCT、InterlispのRECORDパッケージ - oblistからobarray、package、moduleなどへの発展 - ハッシュ表: 速度、オブジェクトの間に関係を作る一方で、不透明なものと してそれらをみなすこと(ポインタを作るためにどちらかを修正する必要は ない)、属性リストの使用の低下、オブジェクトが回収されることを妨げな い弱いハッシュリンク(ゆえに、弱いリンクをもつハッシュ表はキャッシュ として働く) - プログラミング環境の戦略についての話: ファイルベース対メモリベース; プリティプリンティング; Lispベースのエディタ、とりわけ構造編集対 EMACS; プログラミングスタイルへの機械的なプリティプリンティングの影 響; ツールの集合を買うこと; ツールを可能にする言語の機構やフック: ト レース、advice, inspect, evalhookなど - クロージャ(ダイナミックとレキシカル - Moses 1970へさかのぼって) - 非局所脱出: errset/err, catch, call/cc, unwind-protect, Interlispが もっていたもの全て、外側のPROGへのGO、レキシカルスコープのGOとRETURN (Common Lisp)、一般的な言語機構として、そして実装に対する意味として の継続 4 言語の実験室としてのLisp Lisp文化の興味深い面は、それらを取り囲む多くの他のプログラミング言語と 対照的に、おもちゃの方言がかなりの敬意をもって見られることである。Lisp は、その歴史の間ずっと、言語の実験室として用いられてきた。システムが提 供する機構であるかように見える方法で、Lispへ新たな関数を加えるのは些細 なことである。マクロやCLISP、あるいはそれらと同等のものがあれば、新た な制御構造あるいはその他の文法構造を加えることはたいへん易しい。それが 失敗するなら、Lispでは、新たな方言に対する完全なインタプリタを書くこと はたった30分の仕事である。これがどれほど驚くべきことかを理解するために は、稼働中のC, Fortran, Pascal, PL/I, BASIC, あるいはAPLシステムで始め ることを想像しよう - その言語であらゆるプログラムを書いて実行できるが、 そのコンパイラあるいはインタプリタに対するソースコードへのアクセスをも たない - それから、以下の3つの練習に取り組むことを考えよう: 1. 言語へKnuthのMetafont言語[Knuth, 1986]でのピタゴラスの和と類似の新 たな算術オペレータを加える: a++bは√(a^2+b^2)を計算するのである。そ の言語は、新たなオペレータがその言語の加算や減算に対するオペレータ へ文法的にある程度似ていると大きくなる(Cに対しては、++ではなく+++あ るいは@を使えるだろう; APLに対しては、[+]のような慣例的で恐ろしい重 ね打ちの一つを使う)。 2. その言語へcase文を加える(case文をすでにもっている場合、switchと呼ば れる文を加える。switchは、ちょうどすでにその言語にあるcase文のよう だが、選択されたブランチが実行されると、制御は次のブランチに落ちる; 特別なbreak文あるいは最後のブランチから落ちることがswitch文の実行を 終えるために使われなければならない)。 3. その言語へ完全なレキシカルスコープの関数型クロージャを加える。 そのコンパイラあるいはインタプリタに対するソースコードなしでは、3つの プロジェクト全てはゼロから始めなければならないも同然である。それは我々 の論点の一部である。しかし、FortranコンパイラあるいはAPLインタプリタに 対するソースコードを与えられたとしても、3つの練習の全てはLispで行なう よりもずっと難しいだろう。最初の練習へのLispの答えは1行プログラムであ る(ここではCommon Lispで示されている): (defun ++ (x y) (+ (sqrt x) (sqrt y))) Lispは、組み込みのオペレーションによる使用のために(中置オペレータのよ うな)特別なシンタックスを予約しないので、ユーザ定義の関数は、呼び出し 側にはシステム定義の関数とまさに同じように見える。 2番目は、1ダース行ほどのコードを必要とする(再びCommon Lispで、マクロ の議論のところで述べられたバッククォートシンタックスを用いている): (defmacro switch (value &rest body) (let* ((newbody (mapcar #'(lambda (clause) `(,(gensym) ,@(rest clause))) body)) (switcher (mapcar #'(lambda (clause newclause) `(,(first clause) (go ,(first newclause)))) body newbody))) `(block switch (tagbody (case ,value ,@switcher) (break) ,@(apply #'nconc newbody))))) (defmacro break () '(return-from switch)) ここで我々は2つのマクロを使う。一つはswitchのため、もう一つはbreakのた めであり、それは合わせて以下の文を、 (switch n (0 (princ "none") (break)) (1 (princ "one ")) (2 (princ "too ")) (3 (princ "many"))) (これは、常にmany, too many, one too many, noneのいずれかを印字するか、 何も印字しない)以下に展開することを引き起こすが、 (block switch (tagbody (case n (0 (go G0042)) (1 (go G0043)) (2 (go G0044)) (3 (go G0045))) (return-from switch) G0042 (princ "none") (return-from switch) G0043 (princ "one ") G0044 (princ "too ") G0045 (princ "many"))) これはCコンパイラによって生成されるコードに似ていなくもない。 約100行のコードで3番目の問題を解決するインタプリタの例に関しては、 [Steele, 1978c; Steele, 1978b]を参照のこと。 Lispの添加の実験を行なうことには豊かな伝統があり、それは"ちょっと一 つ新たな機能を加えよう"というものから、実装言語としてLispを用いて完全 に新たな言語を発明することにまでわたっている。この活動は、1960年代終わ りから1970年代初めの間にMITで特に徹底的に続けられたが、スタンフォード 大学、カーネギーメロン大学、インディアナ大学といった他の組織でも同様だっ た。当時は、見本として新たなプログラミング言語を出すことで、プログラミ ングスタイルに関するアイディアの集合を具体化することが通例だった(これ はLispコミュニティの外でも同様に真だった; Algolのような、特にPascalに 触発された言語の同時期の急増を目撃している。しかし、Lispは、多くの人月 の努力を必要とする大改造に取り組むことと同様に、少量のオーバーヘッドで 十分試してみることを便利にした)。 Lispに基づく言語の最初期の一つはMETEOR [Bobrow, 1985]であり、Lispの シンタックスをもつCOMIT (語呂合わせに注意)の一バージョンだった。COMIT [MIT RLE, 1962a; MIT RLE, 1962b; Yngve, 1972]は、平坦な、線形の記号的 トークンのワークスペースの内容に対してルールの集合を繰り返してマッチさ せるパターンマッチング言語だった; それはSNOBOLの前身であり、OPS5 [Forgy, 1977]のようなルールベースの言語の祖先だった。METEORは、IBM 7090上で動作するMIT Lisp 1.5システムの中に組み込まれた。METEORのための Lispコードは、300の80カラムのカード(他よりも多くの空白を持つものがいく らかある)よりもやや少ない。対して、COMITインタプリタの7090の実装は、 Yngveによると、約10000語あるいはメモリを占めた; これがアセンブリ言語コ ードの約10000行を表すと仮定すると、他の言語をプロトタイプするための高 級言語としてのLISPの有効性の初期の例として、これを見ることができる。 別の初期のLISPに基づいたパターンマッチング言語はCONVERT [Guzman, 1966]だった。METEORは、Lispデータ構造として表現されたほぼまっすぐな COMITの実装だったが、CONVERTは、COMITのパターンマッチング機能をLispの 再帰的なデータ構造と合併し、再帰的に定義されたパターンのマッチングを任 意のLispデータ構造に対してできるようにした。 Carl Hewittは、Planner [Hewitt, 1972]と呼ばれる定理証明のための非常 に野心的なLispのような言語を設計した。その主な貢献は、パターン指向の呼 び出しや、ゴール指向の探索に対する実装メカニズムとしての自動的なバック トラッキングの使用での進歩から成っている。それは、元々考えられていたよ うに完全に実装されることはなかったが、Lispの歴史での3つの別の重要な開 発を駆り立てた: Micro-Planner, Muddle, そしてConniverである。 Gerald Jay Sussman, Drew McDermott, そしてEugene Charniakは、 Micro-Planner [Sussman, 1971]と呼ばれるPlannerのサブセットを実装し、や がてMacLispになるMIT PDP-6 Lispシステムの中に組み込まれた。実装された ものとしてのその言語の意味論は、完全には形式化されていなかった。その実 装技術はややアドホックで、ある種の複雑な場合には正しく動作しなかった; マッチャは2つのパターンをマッチするように設計され、そのそれぞれは変数 を含んでもよいが、完全なユニフィケーションアルゴリズムを使わなかった (ずっと後で、Sussmanは、Prologについて学ぶなかで、Prologは Micro-Plannerの最初の正しい実装のようだとGuy Steeleへ言った)。 Plannerの一バージョンがPOP-2でも実装された[Davies, 1984]。 言語Muddle(後にはMDL)は、拡張されたLispの一バージョンであり、いくつ かの点では競争相手だった。MIT AI Laboratoryから別れたが545 Technology Squareの同じ建物にあった、MITのDynamic Modeling Groupで設計され使用さ れた。この努力は、Gerald Jay Sussman, Carl Hewitt, Chris Reeve, そして David Cresseyによって1970年の終わりに始まり、Bruce Daniels, Greg Pfister, そしてStu Galleyが後に加わった。それは"... Lispの後継として、 Dynamic Modeling Systemに対する候補となる手段として、そしてPlanner-70 の実装に対するベースになり得るものとして"設計された[Galley, 1975]。 MuddleとLisp間の競争、そしてSussmanは両陣営に通じていたという事実は、 ある程度、相互の交流を生み出す結果になった。MuddleのI/O、割り込みの扱 い、そしてマルチプログラミング(すなわちコルーチン)機構は、当時MacLisp よりもずっと進んでいた。Muddleは、PDP-10 MacLispがそれまでもっていたも のよりも,ずっと複雑なガーベジコレクタや、より大きなアプリケーションサ ブルーチンのライブラリ、とりわけグラフィックスのためのライブラリをもっ ていた(当時の何人かのLispパルチザンが答えたことには、Muddleは、もっぱ らサブルーチンのライブラリをコード化するために使われ、メインプログラム が存在しない! しかし実際には、いくつか実際のアプリケーションがMuddleで コード化された)。Muddleは、Conniver, Lisp Machine Lisp, そしてCommon Lispによって後に採用されたラムダリストのシンタックスマーカOPTIONAL, REST, そしてAUXを導入した。 言語Conniverは、Micro-Plannerのわかっていた制限、とりわけその制御構 造への反応として、1972年にDrew McDermottとGerald Jay Sussmanによって設 計された。古典的な論文であるWhy Conniving Is Better Than Planning [Sussman, 1972b; Sussman, 1972a]で、彼らは、網羅的探索を行なうために使 われるFORALLループの集合を表現するには、自動的なネストしたバックトラッ キングは過度に複雑なだけの方法であると論じた: Plannerのバックボーンであるバックトラック制御構造は、その問題 の解決においては、助けというより障害であるというのが我々の主張で ある。とりわけ、自動的なバックトラッキングは非効率的なアルゴリズ ムを助長し、何が起こっているかをユーザから隠し、パワフルな名前を もつがそのパワーはほんの表面的なものであるプリミティブでユーザを 誤解させる。 Conniverの設計は、プログラマの手の中に非常に明示的に制御の流れを委ねた。 そのモデルは、コルーチンの極度の一般化だった; アクティブな制御の場所は ただ一つしかないが、あるものから別のものへとアクティブな場所を明示的に 移動するための任意の数の論理的なスレッドとプリミティブがあった。この設 計は、(後にInterlispとして知られる)BBN-LispにDaniel BobrowとBen Wegbreitによって導入および実装された"スパゲッティスタック"モデル [Bobrow, 1973]に強い影響を受けた。スパゲッティスタックのように、 Conniverはデータ環境と制御環境の記法、およびいずれかの上にクロージャを 作成することに対する可能性を提供した(後のScheme言語の研究は、データ環 境と制御環境は、Lispのような言語の解釈の中で対称的な役割を果たさないと いう点を明らかにした[Steele, 1977a])。Conniverは、主に実装の考慮から生 じたという点でスパゲッティスタックと異なっていた。Conniverの主なポイン トは、一般性と実装の容易さだった; それはLispで書かれ、Lispのリスト構造 として制御とデータ環境を表現したので、Lispのガーベジコレクタが破棄され た環境の回収を扱えるようになった。他方で、スパゲッティスタックの実装は、 低いレベルでのLispシステムへの構造的な変更を伴った。それは、可能なとき にはいつでもスタックのような割り当てと解放の振る舞いを許すことで、効率 の問題を扱った。そのポリシーは、使うときには払うが、使わないなら払わな いというものだった: クロージャを作らないプログラムは、制御とデータ環境 のヒープ管理のオーバーヘッドを払うべきではない。 [以下のテキストは非常に不完全であり、書き入れられる必要がある。] MLISP2 [Smith, 1973], LISP70 [Tesler, 1973], QA4, SAIL言語へのLEAP拡 張[Swinehart, 1972; Feldman, 1972], そしてPLITSのような、MITの外でのパ ターンマッチングとバックトラッキング言語についてここで述べる必要がある。 ロチェスターでの1977 AIPL Conferenceをチェックする必要がある。 [スケッチの節の終わり。] 同じ頃、Carl Hewittと彼の学生たちは、計算のアクタモデルを開発し始め た。その中では、全ての計算の実体は、プログラムであれデータであれ、アク タ: つまりメッセージを受け取って反応できるエージェントである。Conniver によって明らかにされた不法の行為は、このモデルでいっそう明白にされた; 全てはメッセージパッシングであり、全ては継続の上で動作したのである。 Hewittと彼の学生であるBrian Smithは、当時の多くの研究グループとのやり とりについてコメントした[?]: PLANNERの初期の研究はMITでなされ、IJCAI-69 [Hewitt, 1969]で発 表された。1970年、興味をもった研究者たち(Peter Deutsch, Richard Fikes, Carl Hewitt, Jeff Rulifson, Alan Kay, Jim Moore, Nils Nilsson, そしてRichard Waldingerを含んでいる)のグループは、意見 を交換するためにPajaro Dunesで集まった... 1972年、Alan KayはMIT でセミナーを開いた。そこで彼は、Landin, Evans, そしてReynoldsのラムダ算法言語での"手続き的データ構造"に 対してある限られた程度、そしてSIMULA-67で広くなされたように、意 図的なデータ構造の定義を使うことと、それらへメッセージを渡すこと の重要性を強調した。彼の論点は、データ型自身だけが、全ての定めら れたオペレーションをどのように実装するかを本当に"知っている"とい うことだった。それ以前にも、我々自身の研究の中で手続き的データ構 造に注目していた... しかし我々は、手続き的データ構造は、ある種の 利点はあるが、実用のためにはあまりに非効率的だと誤解していた。 Kayの講義は回答を表明していた... 我々は、データ構造への手続き 的な情報の組み込みの原理を拡張するために...彼のアイディアをどの ように使うべきかをすぐに理解した。要するに、それぞれのデータ構造 の型は、受け取るそれぞれの種類の要求に対して何をすべきかの多少の 計画になる... Kayは、これらのアイディアを実装するために、トークンストリーム 指向のインタプリタをもつSMALLTALKと呼ばれる言語を提案した... [その頃、] Peter BishopとCarl Hewittは、何年もの間PLANNERのよ うな問題解決システムを悩ませ続けていた制御構造問題への一般的な解 決法の獲得を試みるために働いていた。Sussmanは、我々が非常に重大 な欠点があると感じた"可能性リスト"を指向する解決法を提案していた... 単にtry-nextを用いてその中身を見ることは、不幸なグローバルな副作 用を引き起こし得る... [それは]Conniverプログラムをデバッグや理解 しづらくする。SMALLTALKのトークンストリームは、Conniverの可能性 リストと同じ副作用の問題をもつ。その講義の後、Hewittは、制御構造 問題はトークンストリーム指向のインタプリタに対する彼の案に伴うこ とをKayへ指摘した。 1972年の12月までに、我々はSMALLTALKとSIMULA-67のメッセージメカ ニズムを一般化することに成功した; Krutar, Balzer, そしてMitchell のポートメカニズム; そして、以前のPLANNER-71のCALL文を普遍的な通 信メカニズムにした。我々の一般化は、HeweittがSMALLTALKの設計の中 でKayへ指摘した制御構造問題を解決した。我々は、新たな、言語に依 存しない、マシンに依存しない、ふるまいの計算モデルの一部としてア クタ伝達通信プリミティブを開発した。計算のアクタモデルの開発と効 果は、この研究領域への我々の主な独創的な貢献である... 以下は、計算のアクタモデルの開発で影響を受けた主なものである: - 手続き的な組み込みは、"関数的データ構造"でのChurch, Landin, Evans, そしてReynoldsによる仕事を一般化する我々の以前の試みの コンテキストの中で、データ構造をカバーするように拡張されるとい う[Alan] Kayによる提案 - Landin, Mitchell, Krutar, Balzer, Reynolds, Bobrow-Wegbreit, そしてSussmanのコルーチンの制御構造での仕事を大掃除し、そして 一般化しようとする我々の以前の試みのコンテキスト - LOGOでの計算に対するSeymour Papertの"小さな人"のメタファの影響 - 能力に基づく保護の計画の限界と複雑さ。各アクタの伝達は、事実上、 アクタマシン上で本質的な保護を効率よく提供する領域間の呼び出し である。 - PLANNERの前の世代を開発した経験。本質的には、PLANNER-71言語全 体(いくつかの拡張も一緒に)は、エジンバラ大学でPOP-2でJulian Daviesによって実装された。 計算のアクタモデルに関しては、制御構造は単にメッセージを渡すこ とのパターンである... アクタ制御構造は、Conniverの制御構造を超え る以下の利点をもつ: - Conniverの制御構造へのアプローチがもつ重大な問題は、プログラマ (人間であれマシンであれ)は、アクティベーションレコードや可能性 リンクといった低いレベルのデータ構造に関して考えなければならな いことである。アクタアプローチは、プログラマが、プログラムされ る領域に自然に生じるオブジェクトのふるまいに関して考えられるよ うにする... - アクタの伝達は、副作用から完全に自由である... - Conniverの制御メカニズムはモジュール性の原則を破る... Dijkstra は、gotoの使用は悪い構造のプログラムと関係していると言った。我々 はこの判断に同意するが、その理由は、gotoは十分にパワフルなプリ ミティブではないからだと感じる。gotoがもつ問題は、メッセージが ターゲットへ制御と一緒に送られ得ないことである... - そのプリミティブの制御構造のために、Conniverのプログラムは書く ことやデバッグすることが難しい... Conniverのプログラムは、プロ グラマに対して非常に明らかな理由もなく無限ループに入りがちであ る。 それにもかかわらず、Conniverは、容易に行なわれ得るゴール指向の計 算の一般性を増しているという点でMicro-Plannerを超える実質的な進 歩を示している。しかし、この一般性の増加は、問題解決の言語のレベ ルを下げることの代償でやってくる。ユーザが、"可能性リスト"や "a-links"のような低いレベルの実装の表現を考えることを強いるので ある。我々は、問題解決が、メッセージを渡すことで通信する個人の社 会の問題解決であるような、パラダイムの移行を提案する。 我々は、3つの理由で長々とSmithとHewittを引用した: 彼らの比較による分析 は非常に明快であるため; その一節は、異なるアイディアの間での多くのつな がりがAI、Lisp、そしてその他の言語コミュニティの中のあちこちにあること を例証しているため; そして、アイディアの進化の中でまさにこの点が、まも なくLisp自体の進化に素早くパワフルにフィードバックされる蒸留物を表して いたためである。 Hewittと彼の学生(とりわけHowie Shrobe, Brian Smith, Todd Matson, Roger Hale, Peter Bishop, Marilyn McLennan, Russ Atkinson, Mike Freiling, Ken Kahn, Keith Nishihara, Kathy Van Sant, Aki Yonizawa, Benjamin Kuipers, Richard Stieger, そしてIrene Greif)は、計算のアクタ モデルを具体化するために新たな言語を開発し、MacLispで実装した。この言 語は最初はPlanner-73と呼ばれたが、その名前は後にPLASMA (PLAnner-like System Modeled on Actors) [?; Hewitt, 1975]へ変更された。 PLASMAのシンタックスは見てわかるようにLispに似ている一方で、多くの他 の特殊文字と同様に、何種類かの括弧や(Muddleが行なったように)ブラケット を利用した。Hewittが、その頃に新たに利用可能になったKnightキーボードや Xerox Graphics Printer (XGP)の可能性によってそそのかされたと仮定するこ とは合理的である(Xerox Graphics Printerは最初のレーザープリンタであり、 1インチあたり200ドットだった。そのキーボードは、MIT AI LabのTom Knight によって設計されたのだが、Stanford AI Laboratoryで何年か前に開発された 拡張ASCIIキーボードのMITの同等物だった。Stanfordキーボードのように、 KnightのキーボードはControlキーやMetaキー(それはまもなくEMACSテキスト エディタのためのコマンドセットの開発に引っ張り出されて使われた)、そし てα、β、≡のようなエキゾチックな文字を含むグラフィックスの集合をもっ ていた)。再帰的な階乗関数はPLASMAでは以下のようにみえた: [factorial ≡ (cases (≡> [0] 1) (≡> [=n] (n * (factorial (n - 1)))))] 中置算術オペレータの使用に注目しよう。これは単に賢いシンタックスではな く、賢いセマンティックスである; (n - 1)は、減算オペレータと数1を含んで いるメッセージが、nと名付けられた数/アクタ/オブジェクトへ送られようと していることを真に意味していた。 ある人は、MITでのLispの発展は、1970年代の間、2つの別の道をたどったと 主張するかもしれない。第1の道では、MacLispが馬車馬ツールであり、最大の 効率とコンパクトさのためにアセンブリ言語でコード化され、AI Laboratory やMACSYMAグループのニーズに供した。第2の道は、Hewitt(と彼の学生たち)と Sussman(と彼の学生たち)の間の長きにわたる対話/競争/議論からなっており、 どちらの側もその他の世界からアイディアを引き寄せ、同様にアイディアを生 み出した。第2の道は、それぞれの新たなアイディアの集合が新たな言語の形 式で例証され、素早いプロトタイピングや実験のために通常はLispのような言 語(MacLispあるいはMuddle)の上に実装される場所での、"正しいこと"に対す る探求によって特徴付けられた。 Hewitt/Sussmanの対話の次のラウンドは、もちろん、(2.8節で議論したよう に)Schemeだった; 後知恵では、この発展はその対話で終わったようにみえる ことに気づくが、おそらく、それが探求の道全体を一周させたからである。 Lispから始まり、探索や制御構造、計算のモデルの課題を詳説しようと努め、 最後には古き良きLispへ実際に戻ってきたが、そのLispには一つ違いがあった: レキシカルスコーピング - 要するにクロージャ - が、単にシンタックスだけ ではなくセマンティックスにおいてもLispをラムダ算法と一致させるために必 要であり、それによって、Lispを数理論理学の様々な発展と強く結びつけ、 Lispコミュニティが関数型プログラミングの発展と互いに影響し合うことへの 道を開いた。 (この連係の一つの結果は、年一回のACM Principles of Programming Languages会議での議論のための枠組としてさらに説明することなしでScheme を当然のものと考えることが、これまでの何年間はきわめてまともだったとい うことである!) Hewittは、アクタモデルが、ラムダ算法の目につきやすい面 を捕らえることができることに言及した; Schemeは、ラムダ算法がアクタモデ ルのほとんど全ての目につきやすい面(副作用と同期だけは除く)を捕らえるこ とを例証した。 SussmanとSteeleは、この新たな見方で、アクタに基づく言語と同様にLisp のようなセマンティックスをまさに懸命に見始めた。Schemeは、Lisp 1.5と比 較してすらずっと単純だったので、いったんレキシカル環境とクロージャを維 持するオーバーヘッドを受け入れたら、紙一枚(あるいは、30行の2画面)の Lispでそれに対する完全なインタプリタを書けるだろう。これは、言語や実装 のアイディアを伴うきわめて素早い実験をできるようにした; ある時点では、 SussmanとSteeleは、一週間に10もの新たなインタプリタのテストと測定を行 なっていた。それらの結果のいくつかは、The Art of the Interpreter [Steele, 1978b]に要約された。特に興味深い点は、名前による呼び出しと値 による呼び出しのパラメータの比較だった; この中で、彼らは論文CONS Should Not Evaluate Its Arguments [Friedman, November]で検討されたイン ディアナ大学での仕事に影響を受けた。 素早い変化を自身に受けやすいこと以外にも、Schemeは、さらに他の言語の 素早いプロトタイピングのための実装の基礎としても役立ってきた。言語の意 味を形式的に記述する理論家の間で人気のあるテクニックの一つは、表示的意 味論を与え、その表示的意味論で各部分とそれらの関係に関してそれぞれの構 造の意味を記述することである; ラムダ算法がこの記法の接着剤である。 Schemeは、利用可能なプログラミング環境で、ラムダ算法の単純で実用的な実 装を事実上提供するので、表示的意味論は、新たな言語のための動作するイン タプリタを生じるようにSchemeへまっすぐに複写され得る。 Schemeは、正しく設計されたLispは、制御構造やメッセージパッシングを管 理することに必要なあらゆる柔軟性(全てがシンタックスではないとしても)を 与えることを示した一方で、Lispに基づくAI言語の開発のその他のゴールの解 決はしなかった: ゴール指向の探索あるいは定理証明の自動的な管理である。 Scheme以後、いくつかの新たなLispに基づく言語がSussmanと彼の学生たちに よってこの方向で開発された。それらは制約に基づく[Sussman, 1975a; Stallman, 1976; Steele, 1979; Kleer, 1978b]システムや、非単調論理に基 づく真偽維持システム [Kleer, 1978a; McAllester, 1978]を含んでいる。依 存指向のバックトラッキングのテクニックは、年代順のバックトラッキングの "FORALLループの巨大な入れ子"効果を除去した。時がたつにつれて、この研究 の線は、言語設計の問題よりもデータベース設計の問題になり、主流のLispの 進化へフィードバックされるにはまだ至っていない。 しかし、人工知能アプリケーションのための言語の開発は他の場所で続いて おり、Lispはそれらを実装するために選ばれる媒体であり続けている。1980年 代始めから、Cがしばし代替選択肢となり、とりわけ効率が主要な関心である ところではそうだった。Lispの実装テクニックの改良、とりわけコンパイルと ゴミ集めでの改良は、その振り子を少しゆり戻した。 1980年代始めのAIブームの間、"エキスパートシステム"が決まり文句だった; これは、METEORやCONVERTと表面的にはそれほど違わない言語で書かれたルー ルベースのシステムを意味すると通常は理解された。OPS5はこの時期の有名な ルールベースの言語の一つであり、XCON(VAX設置のコンフィグレーションを行 なうためのエキスパートシステムであり、Digital Equipment Corporationの ためにカーネギーメロン大学で開発された)は主たるアプリケーションサクセ スストーリーだった。OPS5は最初はLispで実装された; 後に、効率のために BLISS [Wulf, 1971] (おおよそCと同じ意味論的なレベルをもつ、CMUで開発さ れDECでサポートされたシステム実装言語)で再コード化された。 別の重要なAI言語のカテゴリーはフレームに基づくものだった; よい例は KRL (Knowledge Representation Language)であり、Interlispで実装された。 Lispでのその他の実験の方向は、並列性の領域である。初期の開発は割り込 みハンドリングやマルチプログラミングに対する機構を含んでいた一方で、真 のマルチプロセッシングは、(ある場合には、その目的のために作られた)適切 なハードウェア機構が利用可能な場合にのみ発展した。S1 Lisp [Brooks, 1982a]は、S1システムの複数のプロセッサを用いるように設計されたが、(S1 Lispのたいへん多くの他の機能のように)その部分は実際に動作することはな かった。最も重要な初期の"真の"並列Lisp実装のいくつかは、Multilisp, Qlisp, そしてButterfly PSLである。 Multilisp [Halstead, 1984; Halstead, 1985]は、MITでのBert Halsteadと 彼の学生たちの仕事だった。Schemeに基づいており、主にfutureの記法に頼っ ていた。futureは一種の洗濯のチケットのようなもので、いったん計算し終え れば後で値を配達するという約束である。MultilispはPCALL構造も提供した。 それは本質的には、関数を呼び出す前に並列に(そして完全に)引数を評価する 関数呼び出しだった。したがってPCALLは、futureの使用に対して、多くの目 的のためには十分であるようなある種の構造化された規律を提供する。 Multilispは、32個のMotorola 68000プロセッサの集まりであるConcertマルチ プロセッサ上で動作した。MultiSchemeはMultilispの子孫であるが、BBN Butterfly [Miller, 1987]のために後に実装された。 Butterfly PSL [Swanson, 1988]は、BBN Butterfly上でのPortable Standard Lisp [Griss, 1982]の実装だった。それも同様に、並列プロセスを 生み出すためにfutureに完全に頼っていた。 Qlisp [Gabriel, 1984; Goldman, 1988]は、スタンフォード大学でRichard GabrielとJohn McCarthyによって開発された。それは、既存のCommon Lisp の 制御構造と並列している(しゃれのつもり)多くの並列制御構造、とりわけ QLET, QLAMBDA, そしてQCATCHでCommon Lispを拡張した。その計算モデルは、 プロセスのグローバルなキューと、プロセスを生み出してプロセス間の相互作 用とリソースの消費を制御する手段を必要とした。たとえば、QLAMBDAは3つの 種類の関数を作り出すことができた: 通常の関数。LAMBDAによって作り出され るものと同じ; 熱望(eager)している関数。作成されると別のプロセスを生み 出すだろう; そして遅延された関数。呼び出されると別のプロセスを生み出す だろう。QlispはAlliant FX8上で実装され、最初のコンパイルされた並列Lisp の実装となった。 Connection Machine Lisp [Steele, 1986]は、細粒度のデータ並行性をサポ ートすることを意図したxappingという新たなデータ構造で拡張されたCommon Lispの方言だった。xappingは実装上は配列、ハッシュ表、そして連想リスト の奇妙なハイブリッドだった; 意味論的には、それは順序づけられたインデッ クスと値のペアの集合である。その言語のプリミティブは、並行にxappingの 全ての値を処理するように調整されており、それらに関連づけられたインデッ クスによって、別のxappingからの値を合わせる。そのアイディアは、インデッ クスは仮想プロセッサに対するラベルであるというものだった。記憶管理シス テムがその仕事を行なう場合、同じインデックスをもつ値は同じ物理的なプロ セッサに実際に存在し、プロセッサ間の通信は、異なるインデックスをもつ値 の相互作用の結果としてのみ生じるだろう。Connection Machine Lispは - 多 くのLispの表現上の利点をもつAPLの記号バージョンのようなもの - プログラ ムすることが適度に快適だった一方で、実際は、必要とされる記憶管理は効率 よく実装することが非常に難しかった。Connection Machineに対する(以前に CMUのScott Fahlmanの元でSpice Lispで働いていた)Skef Wholeyによるプロト タイプの実装は、しばらくThinking Machinesで研究のツールとして使われた が、製品としてリリースされることはなかった。それは単純なプログラムに対 しては良好に動作したが、プロトタイプの記憶域アロケータは、xappingがネ ストしていると良好にはふるまわなかった。それは、Wholeyが博士号をとるた めにCMUへ戻るときには後回しにされたままだった。SabotのParalation Lisp [Sabot, 1988]は、Connection Machine Lispでの通信制御の問題への反応とし て一部は設計された。Connection Machine Lispの主要な貢献は、説明の手段 としてSchemeのようなインタプリタを用いて、明示的な並列操作の解釈をFP [Backus, 1978]のような関数型言語に供給する、いくつかの理論的で実際的な 結果を考え出したことだった。Steeleは、ネストしている並列性のそれ以上の 帰結を後に探求し、並列プログラムでの競合状態を発見できる、さらにもう一 つのSchemeのようなインタプリタを示した[Steele, 1990a]。 要約すると: Lispは、2つの理由で、言語の実験のための素晴らしい実験室 である。第一に、たった1ダースかそれくらいのプリミティブをもつ、とても 小さな部分集合を選ぶことができ、それでも認識できる程度にLispのような言 語のクラスの要素である。新たなプラットフォームの上で、様々な選択肢を用 いて、そのような小さな言語をブートストラップすることはたいへん容易であ る。それが将来有望にみえる場合、後で長い快適の洗濯リストを太らせること ができる。第2に、既存のLispの実装の中でそのような新たな方言をブートス トラップすることは特に容易 - 1時間以下の仕事 - である。ホストの実装が 基本的な方法において新たな方言と異なる場合でさえ、単に言語のインタプリ タを書くことのために明白に便利なプログラミング言語であるのと同様に、算 術やI/Oのようなプリミティブな操作を提供できる。汎用の、リスト構造指向 のシンタックスを用いて生きていける場合、セマンティックスを再プログラミ ングする野外演習を一日もてる。それを正しく行なった後でも再設計するため の時間は十分あるし、どうしても行なわなければならない場合、パーサの額を ピシャリと打てばよい。 5 なぜLispは多様なのか このLispの進化の歴史書の中で、我々は、Lispはもっと広く使われている他の 言語より入念な、そして複雑な歴史をもっているようであることを見てきた。 ほとんど全ての小さな研究グループが自身のバージョンのLispをもつようにみ えるだろうし、言語の概念上の多様性と同じくらい多くのLispがあるようにみ えるだろう。それを説明する、何がLispに関してそれほど特別なのか、または 異なっているのかを尋ねることは自然である。 5つの基本的な理由がある: 理論的な基盤、順応性、対話的で徐々に増加す る性質、オペレーティングシステムの機構、そしてその上で働くことを選ぶ人々 である。 理論的な基盤。Lispは再帰関数の理論と計算可能性の理論の地歩に基づいて 作られた。そのきわめて純粋な形式は、数学の推論や証明に有用である。した がって、多くの理論的な興味がある研究者は、その中でアイディアを表現し仕 事を行なうために、LispまたはLispのような言語を採用した。そのような理由 で、我々は、新たな言語構造が説明されたり、既存の構造が説明されたり、プ ログラムの特性が証明されたり、証明のテクニックが探求されたりする、多く のLispに基づいた論文を見るのである。 結論は、LispやLispのような言語は、常に基本的な言語研究の最前線にある ということである。そして、より実際的な考え方の理論的な研究者にとって、 Lispでアイディアを実装することも普通のことである。 順応性。新たな言語機能を用いて実験することがLispでは容易である。なぜ なら、拡張がユーザにとって元の言語から区別ができないようなやりかたで Lispを拡張することが可能だからだ。最初は、これはマクロの使用を通じて達 成された。マクロは1963年からLispの一部である[Hart, 1963]。Lispのマクロ は、展開を計算するための計算エンジンとしてLispを使用すると、他の言語の 文字列処理のメカニズムよりも言語を拡張するための効果的な方法だと証明さ れている。さらに、そのようなマクロに基づく拡張は、他の言語コミュニティ では見られないようなやりかたでLispコミュニティ内に受け入れられている。 さらに、より最近のLispの方言は、型システムを拡張するためのメカニズム を提供している。これは、人々が新たなデータ型を用いて実験できるようにす る。もちろん、他の言語もこのメカニズムをもっているが、Lispでは、データ 型付けのメカニズムは、完全に新たなコンピューティングのパラダイムがLisp の中に構築され得るように、パワフルなマクロ機構や言語の関数的性質に結合 されている。たとえば、Lispと新たなパラダイムの間の縫目が本質的に不可視 であるような方法でLispに実装されたデータ駆動パラダイム[Sussman, 1971]、 可能な世界パラダイム[McDermott, 1974]、そしてオブジェクト指向パラダイ ム[Moon, 1986] [Bobrow, 1986]を見ている。 対話的で徐々に増加する性質。Lispでプログラミングの問題への解決法を探 求することは容易である。なぜなら、解決法の一部を実装し、テストし、修正 し、設計を変更し、そしてその変更をデバッグすることが容易だからだ。長っ たらしい編集-コンパイル-リンクのサイクルはない。このため、Lispは素早い プロトタイピングや、完成していない - そしてあるいは完成することが不可 能な - 着手の計画に直面しているとても大きなプログラムの構築に有用であ る。したがって、Lispは、他の言語を用いるにはあまりに印象的な領域を探求 するためにしばしば使われてきた。 このLispの特徴は、冒険好きや開拓を行なう人にとって魅力的なものにする。 オペレーティングシステムの機構。多くのLispの実装はオペレーティングシ ステムを思わせる機構を提供する: コマンドプロセッサ、自動的な記憶領域管 理機構、ファイル管理、表示(ウィンドウ、グラフィックス、マウス)機構、マ ルチタスキング、コンパイラ、インクリメンタル(再)リンカ/ローダ、シンボ リックデバッガ、パフォーマンスモニタリング、そしてときにはマルチプロセッ シング(並列プログラミング)。 これはLispでオペレーティングシステムの研究を行なうことや、完全なオペ レーティング環境を提供することが可能であるということを意味する。対話的 で徐々に増加する性質と結合されると、洗練されたテキストエディタを書くこ とや、ホストコンピュータの本来のオペレーティングシステムにとって代わる ことが可能である。したがって、Lispシステムは、幅広い種々の互換性のない プラットフォームで強固な移植性を供給するオペレーティング環境を提供でき る。 このことはLispを研究者にとって魅力的な媒体にし、それによってさらに Lispを多様化するのである。 人々。もちろん、言語自身が多様化するのではなく、人々が言語を多様化す るのである。上述の4つの要因は、単にLispに人々を引き付けるのに役立つに すぎず、彼らがLispを用いて実験するためにそれらに対して機構を供給するの である。Lispへ引き付けられた人々が新たな言語の代案を探求することに興味 がなかったなら、Lispは多様化しなかっただろうから、Lispには冒険好きに人々 を引き付ける何かがあるに違いない。 中でも、Lispは人工知能の言語である。そして、AIは全てのプログラミング の仕事で最も困難でエキゾチックなこと: 認知や知能の模倣または理解を探求 することを志向する計算機科学の分野である。AIへ引き付けられる人々は一般 的に創造的で大胆であり、言語設計者や実装者は、自身がしばしばAI研究者で あるか以前はAI研究者だった人々なので、当然この性質になる。 Lispは、それらの機能 - あるいはそういうもの - が初期のAIの進歩のため に必要とされたので、固有の特質の集合を提供する。AIが商業的な関心事の題 目だったときだけは、AI企業はLisp以外の言語に顔を向けた。 その他の魅力は、Lispはエキスパートの言語であることであり、我々の目的 のためには、Lispは未熟なプログラマが頑丈で信頼性が高いソフトウェアをコ ード化するために設計された言語ではないことを意味する。したがって、コン パイル時の型チェックはほとんどなく、モジュールシステムはほとんどなく、 言語に組み入れられた安全あるいは統制構造はほとんどない。それはアナーキ ーな言語であり、一方多くの他の言語は(ハッカーたちが心に抱いているよう に[Raymond, 1991])"ファシスト"である。 キーポイントは、ある種の人がLispへ引き付けられ、その人はある方法でプ ログラムすることや、新たな言語の設計を探求すること、そして創造性を実証 することや用いることに興味があるということである。 6 大統合 探求するように関連づけたかもしれないがそうしなかった現象は、80年代の大 統合だった。総体的なプログラミング言語の歴史を見ると、1960年代と1970年 代の間、多量のプログラミング言語が開発され、それらの多くはとても小さく 孤立したグループによるものだったことは明らかに思える。これは我々の多様 化のモデルに当てはまる - 多様化は、十分に大きくパワフルな受容グループ がないとき、そして言語設計者が孤立しているときに起こる。 しかし、1980年代には、ほとんど全ての言語開発は統合だった - 80年代は 退屈だった。 これに対するいくつかの可能な説明がある。それぞれは可能な受容グループ に関してであり、そしてもちろん、それらの説明は結合される。一つの説明は、 ネットワーク - 特にARPANet - が固まり、ずっと多くの人々にアクセス可能 になったことである。これは大きな受容グループと、同時に移植性や標準化に 対する圧力を作り出した。 2番目の説明は、1980年代はPC市場の凝固が生じ、そのことが商業的な受容 グループと、ここでも移植性に対する圧力を供給したというものである。 3番目の説明は、商業的な受容グループと、大きなネットワークに基づくユ ーザ指向の受容グループの両方においてワークステーション市場が発展し始め、 名声と富を追求する中で多くの多様化の才能が尽きたというものである。 この説明の変形は、それほど才能のないプログラマが、頑丈で、信頼性があ り、保守可能なソフトウェアを開発することを助けるための指導や規律を提供 するときには、商業的な言語が最上だというものであり、それらの目標を達成 するために60年代や70年代に開発された十分に確立されたテクニックや経験が あるとしても、そのような言語は1980年代に多様化する人々にとってはあまり おもしろくないのである。 4番目の説明は、個々の概念や機能を探求することではなく、完全な言語を 設計することがあまりに難しくなった、あるいはあまりに時代遅れになったと いうものである。60年代や70年代には、一人の人間あるいは小さなグループが、 有用であるために十分な処理性能をもつ言語の設計と実装を行なうことが可能 だった。1980年代には、商業的な圧力が、商業的にサポートされた言語での処 理性能の改善を強制したので、受容グループをもつ言語を生み出すことでさえ あまりに大きな仕事になった。統合フェーズに言語を入れるために十分なほど 大きいかパワフルなものは言うまでもない。 1980年代に言語の設計や実装を行なうことは、おそらく身分の保障や名声や 昇進を達成するにはあまりに難しい手段なので、その活動をやめる傾向にある。 以下は、どのように他の人達が述べたかである: LISPは、これまで開発された全ての他のタイプのプログラミング言語か ら明らかに逸脱しているという意味において普通ではない… LISPの理 論的な概念と意味は、その実際的な使用法をはるかに越えている。 - Jean E. Sammet [?, p. 406] これがLispのような言語の大きな長所の一つである: 複合式を形成する とても少ない方法しかもたず、ほとんど文法構造がない… すぐに我々 はその言語の文法的な詳細を忘れ(なぜなら、そんなものはないからだ)、 真の課題を進めることになる。 - Abelson and Sussman [?, p. xvii] 糖衣構文は、セミコロンの悪性腫瘍を引き起こす。 - Alan Perlis Lispに関して私が好きなことは、足指の間にビットを感じられることで ある。 - Drew McDermott [?] Lispは、パーシングが初歩的な仕事として扱われ得るほど単純なシンタッ クスをもっている。したがって、パーシングの技術はLispプログラムの 中ではほとんど何の役割も演じないし、言語プロセッサの構築は、成長 率や大きなLispシステムの変更の障害にはほとんどならない。 - Alan Perlis ([?]への序) Pascalはピラミッド - 人目を引く、あっと言わせるような、正しい場 所へ重い石の塊を押していく軍隊によって作られた静的な構造物 - を 作るためのものである。Lispは有機体を作るためのものである… - Alan Perlis ([?]への序) Lispは、自由なスタイルと柔軟性を楽しむ人々が選ぶ媒体である。 - Gerald Jay Sussman (The Little Lisperへの序, p. ix) おい、Quux: こんな論文をハックするのはやめて、代わりにLispをハッ クしようぜ! - rpg (最終編集者) 7 結び [以下のテキストは非常に不完全であり、書き入れられる必要がある。] 我々は、なおも作業中である。 [スケッチの節の終わり。] 参考文献 [ACM LFP, 1982] ACM SIGPLAN/SIGACT/SIGART. Proc. 1982 ACM Symposium on Lisp and Functional Programming, Pittsburgh, Pennsylvania, August 1982. Association for Computing Machinery. ISBN 0-89791-082-6. [ACM LFP, 1984] ACM SIGPLAN/SIGACT/SIGART. Proc. 1984 ACM Symposium on Lisp and Functional Programming, Austin, Texas, August 1984. Association for Computing Machinery. ISBN 0-89791-142-3. [ACM LFP, 1986] ACM SIGPLAN/SIGACT/SIGART. Proc. 1986 ACM Conference on Lisp and Functional Programming, Cambridge, Massachusetts, August 1986. Association for Computing Machinery. ISBN 0-89791-200-4. [ACM LFP, 1988] ACM SIGPLAN/SIGACT/SIGART. Proc. 1988 ACM Conference on Lisp and Functional Programming, Snowbird, Utah, July 1988. Association for Computing Machinery. ISBN 0-89791-273-X. [ACM OOPSLA, 1986] Proceedings of the ACM Conference on Objected-Oriented Programming, Systems, Languages, and Applications (OOPSLA '86), Portland, Oregon, October 1986. Association for Computing Machinery. ACM SIGPLAN Notices, 21:11, November 1986. ISBN 0-89791-204-7. [Backus, 1978] Backus, John. Can programming be liberated from the von Neumann style? A functional style and its algebra of programs. Communications of the ACM, 21:8, pp. 613-641, August 1978. 1977 ACM Turing Award Lecture. [Baker, 1978] Baker, Henry B., Jr. List processing in real time on a serial computer. Communications of the ACM, 21:4, pp. 280-294, April 1978. [Bartley, 1986] Bartley, David H., and John C. Jensen. The implementation of PC Scheme. In [ACM LFP, 1986], pp. 86-93. [Bawden, 1988] Bawden, Alan, and Jonathan Rees. Syntactic closures. In [ACM LFP, 1988], pp. 86-95. [Berkeley, 1985] Berkeley, Edmund C., and Daniel G. Bobrow, eds. The Programming Language LISP: Its Operation and Applications. Information International, Inc. and MIT Press, Cambridge, Massachusetts, 1985. [Black, 1985] Black, Fischer. Styles of programming in LISP. In [Berkeley, 1985], pp. 96-107. [Bobrow, 1972] Bobrow, Robert J., Richard R. Burton, and Daryle Lewis. UCI-LISP Manual (An Extended Stanford LISP 1.6 System). Information and Computer Science Technical Report 21, University of California, Irvine, Irvine, California, October 1972. [Bobrow, 1973] Bobrow, Daniel G., and Ben. Wegbreit. A model and stack implementation of multiple environments. Communications of the ACM, 16:10, pp. 591-603, October 1973. [Bobrow, 1985] Bobrow, Daniel G. METEOR: A LISP interpreter for string transformations. In [Berkeley, 1985], pp. 161-190. [Bobrow, 1986] Bobrow, Daniel G., Kenneth Kahn, Gregor Kiczales, Larry Masinter, Mark Stefik, and Frank Zdybel. CommonLoops: Merging Lisp and object-oriented programming. In [ACM OOPSLA, 1986], pp. 17-29. [Boehm, 1986] Boehm, Hans-J., Robert Cartwright, Mark Riggle, and Michael J. O'Donnell. Exact real arithmetic: A case study in higher order programming. In [ACM LFP, 1986], pp. 162-173. [Brooks, 1982a] Brooks, Rodney A., Richard P. Gabriel, and Guy L. Steele Jr. S-1 Common Lisp implementation. In [ACM LFP, 1982], pp. 108-113. [Brooks, 1982b] Brooks, Rodney A., Richard P. Gabriel, and J Steele, Guy L. An optimizing compiler for lexically scoped LISP. In Proceedings of the 1982 Symposium on Compiler Construction, pp. 261-275, Boston, June 1982. ACM SIGPLAN, Association for Computing Machinery. ACM SIGPLAN Notices, 17:6, June 1982. ISBN 0-89791-074-5. [Brooks, 1984] Brooks, Rodney A., and Richard P. Gabriel. A critique of Common Lisp. In [ACM LFP, 1984], pp. 1-8. [Burke, 1983] Burke, G. S., G. J. Carrette, and C. R. Eliot. NIL Reference Manual. Report MIT/LCS/TR-311, MIT Laboratory for Computer Science, Cambridge, Massachusetts, 1983. [Burstall, 1971] Burstall, R. M., J. S. Collins, and R. J. Popplestone, eds. Programming in POP-2. Edinburgh University Press, 1971. [Campbell, 1984] Campbell, J. A., ed. Implementations of Prolog. Ellis Horwood Limited, Chichester, 1984. ISBN 0-470-20045-6. Also published by John Wiley & Sons, New York. [Clark, 1982] Clark, K. L., and S.-.A. Tarnlund, eds. Logic Programming. Academic Press, New York, 1982. [Clinger, 1984] Clinger, William. The Scheme 311 compiler: An exercise in denotational semantics. In [ACM LFP, 1984], pp. 356-364. [Clinger, 1985a] Clinger, William (ed.). The Revised Revised Report on Scheme; or, An Uncommon Lisp. AI Memo 848, MIT Artificial Intelligence Laboratory, Cambridge, Massachusetts, August 1985. [Clinger, 1985b] Clinger, William (ed.). The Revised Revised Report on Scheme; or, An Uncommon Lisp. Computer Science Department Technical Report 174, Indiana University, Bloomington, June 1985. [Clinger, 1988] Clinger, William D., Anne H. Hartheimer, and Eric M. Ost. Implementation strategies for continuations. In [ACM LFP, 1988], pp. 124-131. [Clinger, 1990] Clinger, William D. How to read floating point numbers accurately. In Proc. 1990 ACM SIGPLAN '90 Conference on Programming Language Design and Implementation, pp. 92-101, White Plains, New York, June 1990. Association for Computing Machinery. Proceedings published as ACM SIGPLAN Notices 25, 6 (June 1990). [Clinger, 1991] Clinger, William, and Jonathan Rees. Macros that work. In Proc. Eighteenth Annual ACM Symposium on Principles of Programming Languages, pp. 155-162, Orlando, Florida, January 1991. ACM SIGACT/SIGPLAN, Association for Computing Machinery. ISBN 0-89791-419-8. [Correll, 1979] Correll, Steven. S-1 uniprocessor architecture (sma-4). In The S-1 Project 1979 Annual Report, volume I, chapter 4. Lawrence Livermore Laboratory, Livermore, California, 1979. [Davies, 1984] Davies, J. POPLER: Implementation of a POP-2-based PLANNER. In [Campbell, 1984], pp. 28-49. [DEC, 1964] Digital Equipment Corporation, Maynard, Massachusetts. Programmed Data Processor-6 Handbook, 1964. [DEC, 1969] Digital Equipment Corporation, Maynard, Massachusetts. PDP-10 Reference Handbook, 1969. [DEC, 1981] Digital Equipment Corporation, Maynard, Massachusetts. VAX Architecture Handbook, 1981. [Deutsch, 1973] Deutsch, L. Peter. A LISP machine with very compact programs. In [IJCAI, 1973], pp. 697-703. [Deutsch, 1976] Deutsch, L. Peter, and Daniel G Bobrow. An efficient, incremental, automatic garbage collector. Communications of the ACM, 19:9, pp. 522-526, September 1976. [Deutsch, 1985] Deutsch, L. Peter, and Edmund C. Berkeley. The LISP implementation for the PDP-1 computer. In [Berkeley, 1985], pp. 326-375. [Drescher, 1987] Drescher, Gary. ObjectLISP User Manual. LMI (Lisp Machines Incorporated), Cambridge, Massachusetts, 1987. [Dybvig, 1986] Dybvig, R. Kent, Daniel P. Friedman, and Christopher T. Haynes. Expansion-passing style: Beyond conventional macros. In [ACM LFP, 1986], pp. 143-150. [Eastlake, 1968] Eastlake, D., R. Greenblatt, J. Holloway, T. Knight, and S. Nelson. ITS 1.5 Reference Manual. AI Memo 161, MIT Artificial Intelligence Laboratory, Cambridge, Massachusetts, June 1968. Revised as Memo 161A, July 1969. [Eastlake, 1972] Eastlake, Donald E. ITS Status Report. AI Memo 238, MIT Artificial Intelligence Laboratory, Cambridge, Massachusetts, April 1972. [Fateman, 1973] Fateman, Richard J. Reply to an editorial. ACM SIGSAM Bulletin, 25, pp. 9-11, March 1973. これはコンパイルされたMacLispの 浮動小数点プログラムが同等のFortranコードより速かったテストの結果を 報告している。コードの算術の部分は同一であり、MacLispは、より速いサ ブルーチン呼び出しのプロトコルを用いた。 [Feldman, 1972] Feldman, J. A., J. R. Low, D. C. Swinehart, and R. H. Taylor. Recent developments in SAIL. In Proceedings of the 1972 AFIPS Fall Joint Computer Conference, volume 41, pp. 1193-1202, Stanford, California, November 1972. American Federation of Information Processing Societies. [Fessenden, 1983] Fessenden, Carol, William Clinger, Daniel P. Friedman, and Christopher Haynes. Scheme 311 Version 4 Reference Manual. Technical Report 137, Indiana University, February 1983. [Foderaro, 1982] Foderaro, J. K., and K. L. Sklower. The FRANZ Lisp Manual. University of California, Berkeley, California, April 1982. [Forgy, 1977] Forgy, C., and J. McDermott. OPS, a domain-independent production system language. In Proceedings of the Fifth International Joint Conference on Artificial Intelligence (IJCAI-77), pp. 933- 935, Cambridge, Massachusetts, August 1977. International Joint Council on Artificial Intelligence. [Friedman, November] Friedman, Daniel P., and David S. Wise. Cons Should Not Evaluate Its Arguments. Technical Report 44, Indiana University, 1975 November. [Gabriel, 1982] Gabriel, Richard P., and Larry M. Masinter. Performance of Lisp systems. In [ACM LFP, 1982], pp. 123-142. [Gabriel, 1984] Gabriel, Richard P., and John McCarthy. Queue-based multiprocessing Lisp. In [ACM LFP, 1984], pp. 25-44. [Gabriel, 1985] Gabriel, Richard P. Performance and Evaluation of Lisp Systems. MIT Press, Cambridge, Massachusetts, 1985. ISBN 0-262-07093-6. [Gabriel, 1988] Gabriel, Richard P., and Kent M. Pitman. Technical issues of separation in function cells and value cells. Lisp and Symbolic Computation, 1:1, pp. 81-101, June 1988. ISSN 0892-4635. [Galley, 1975] Galley, S.W., and Greg. Pfister. The MDL Language. Programming Technology Division Document SYS.11.01, MIT Project MAC, Cambridge, Massachusetts, November 1975. [Geschke, 1977] Geschke, Charles M., J Morris, James H., and Edwin H. Satterthwaite. Early experience with Mesa. Communications of the ACM, 20:8, pp. 540-553, August 1977. [Golden, 1970] Golden, Jeffrey P. A User's Guide to the A. I. Group LISCOM Lisp Compiler: Interim Report. AI Memo 210, MIT Project MAC, Cambridge, Massachusetts, December 1970. [Goldman, 1988] Goldman, Ron, and Richard P. Gabriel. Preliminary results with the initial implementation of Qlisp. In [ACM LFP, 1988], pp. 143-152. [Greenblatt, 1974] Greenblatt, Richard. The LISP Machine. Working Paper 79, MIT Artificial Intelligence Laboratory, Cambridge, Massachusetts, November 1974. [Greussay, 1977] Greussay, P. Contribution `a la definition interpretive et `a l'implementation des lambda-langages. Th`ese d'Etat, Universite de Paris VI, November 1977. [Griss, 1981] Griss, Martin L., and Anthony C. Hearn. A portable LISP compiler. Software Practice and Experience, 11, pp. 541-605, 1981. [Griss, 1982] Griss, Martin L., Eric Benson, and Gerald Q. Maguire J. PSL: A portable LISP system. In [ACM LFP, 1982], pp. 88-97. [Group, 1982] Group, Utah Symbolic Computation. The Portable Standard LISP Users Manual. Technical Report TR-10, Department of Computer Science, University of Utah, Salt Lake City, JAN 1982. [Guzman, 1966] Guzman, Adolfo, and Harold V. McIntosh. CONVERT. AI Memo 99, MIT Project MAC, Cambridge, Massachusetts, June 1966. [Hailpern, 1979] Hailpern, Brent T., and Bruce L. Hitson. S-1 Architecture Manual. Technical Report 161 (STAN-CS-79-715), Department of Electrical Engineering, Stanford University, Stanford, California, January 1979. [Halstead, 1984] Halstead, Robert H., Jr. Implementation of Multilisp: Lisp on a multiprocessor. In [ACM LFP, 1984], pp. 9-17. [Halstead, 1985] Halstead, Robert H., Jr. Multilisp: A language for concurrent symbolic computation. ACM Transactions on Programming Languages and Systems, 7:4, pp. 501-538, October 1985. [Harbison, 1991] Harbison, Samuel P., and J Steele, Guy L. C: A Reference Manual. Prentice-Hall, Englewood Cliffs, New Jersey, third edition, 1991. ISBN 0-13-110933-2. [Hart, 1963] Hart, Timothy P. MACRO definitions for LISP. AI Memo 57, MIT Artificial Intelligence Project - RLE and MIT Computation Center, Cambridge, Massachusetts, October 1963. [Hart, 1985] Hart, Timothy P., and Thomas G. Evans. Notes on implementing LISP for the M-460 computer. In [Berkeley, 1985], pp. 191-203. [Hearn, 1971] Hearn, A. C. REDUCE 2: A system and language for algebraic manipulation. In Proc. Second Symposium on Symbolic and Algebraic Manipulation, pp. 128-133, Los Angeles, March 1971. [Henneman, 1985] Henneman, William. An auxiliary language for more natural expression - The A-language. In [Berkeley, 1985], pp. 239-248. [Hewitt, 1969] Hewitt, Carl. PLANNER: A language for proving theorems in robots. In Proceedings of the [First] International Joint Conference on Artificial Intelligence (IJCAI), pp. 295-301, Washington, D. C., May 1969. International Joint Council on Artificial Intelligence. [Hewitt, 1972] Hewitt, Carl. Description and Theoretical Analysis (Using Schemata) of PLANNER: A Language for Proving Theorems and Manipulating Models in a Robot. PhD thesis, Massachusetts Institute of Technology, Cambridge, Massachusetts, April 1972. MIT Artificial Intelligence Laboratory TR-258. [Hewitt, 1975] Hewitt, Carl. How to Use What You Know. Working Paper 93, MIT Artificial Intelligence Laboratory, Cambridge, Massachusetts, May 1975. [Hieb, 1990] Hieb, Robert, R. Kent Dybvig, and Carl Bruggeman. Representing control in the presence of first-class continuations. In Proc. 1990 ACM SIGPLAN '90 Conference on Programming Language Design and Implementation, pp. 66-77, White Plains, New York, June 1990. Association for Computing Machinery. Proceedings published as ACM SIGPLAN Notices 25, 6 (June 1990). [IEEE, 1985] IEEE, New York. IEEE Standard for Binary Floating-Point Arithmetic, ansi/ieee std 754-1985 edition, 1985. An American National Standard. [IEEE, 1991] IEEE Computer Society, New York. IEEE Standard for the Scheme Programming Language, ieee std 1178-1990 edition, 1991. [IJCAI, 1973] International Joint Council on Artificial Intelligence. Proceedings of the Third International Joint Conference on Artificial Intelligence (IJCAI3), Stanford, California, August 1973. [Iverson, 1962] Iverson, Kenneth E. A Programming Language. Wiley, New York, 1962. [Jensen, 1974] Jensen, Kathleen, and Niklaus Wirth. Pascal User Manual and Report. Springer-Verlag, New York, 1974. [Kahn, 1984] Kahn, K. M., and M. Carlsson. How to implement Prolog on a LISP machine. In [Campbell, 1984], pp. 117-134. [Kempf, 1987] Kempf, James, Warren Harris, Roy D'Souza, and Alan Snyder. Experience with CommonLoops. In Proceedings of the ACM Conference on Objected-Oriented Programming Systems, Languages, and Applications (OOPSLA '87), pp. 214-226, Orlando, Florida, October 1987. Association for Computing Machinery. ACM SIGPLAN Notices, 22:12, December 1987. ISBN 0-89791-247-0. [Kernighan, 1978] Kernighan, Brian W., and Dennis Ritchie. The C Programming Language. Prentice-Hall, Englewood Cliffs, New Jersey, 1978. [Kleer, 1978a] Kleer, Johan de, Jon Doyle, Charles Rich, J Steele, Guy L., and Gerald Jay Sussman. AMORD: A Deductive Procedure System. AI Memo 435, MIT Artificial Intelligence Laboratory, Cambridge, Massachusetts, January 1978. [Kleer, 1978b] Kleer, Johan de, and Gerald Jay Sussman. Propagation of Constraints Applied to Circuit Synthesis. AI Memo 485, MIT Artificial Intelligence Laboratory, Cambridge, Massachusetts, September 1978. Also in i[CircuitT heoryandApplications]b[8] (1980), 127-144. [Knuth, 1969] Knuth, Donald E. Seminumerical Algorithms, volume 2 of The Art of Computer Programming. Addison-Wesley, Reading, Massachusetts, 1969. [Knuth, 1974] Knuth, Donald E. Structured programming with GO TO statements. Computing Surveys, 6:4, pp. 261-301, December 1974. [Knuth, 1981] Knuth, Donald E. Seminumerical Algorithms (Second Edition), volume 2 of The Art of Computer Programming. Addison-Wesley, Reading, Massachusetts, 1981. [Knuth, 1986] Knuth, Donald E. The METAFONT Book, volume C of Computers and Typesetting. Addison-Wesley, Reading, Massachusetts, 1986. [Kohlbecker, 1986a] Kohlbecker, Eugene, Daniel P. Friedman, Matthias Felleisen, and Bruce Duba. Hygienic macro expansion. In [ACM LFP, 1986], pp. 151-161. [Kohlbecker, 1986b] Kohlbecker, Jr., Eugene E. Syntactic Extensions in the Programming Language Lisp. Technical Report 109, Indiana University, August 1986. Ph.D. thesis. [Komorowski, 1982] Komorowski, H. J. QLOG: The programming environment for PROLOG in LISP. In [Clark, 1982], pp. 315-322. [Kranz, 1986] Kranz, David, Richard Kelsey, Jonathan Rees, Paul Hudak, James Philbin, and Norman Adams. ORBIT: An optimizing compiler for Scheme. In Proc. 1986 ACM SIGPLAN '86 Symposium on Compiler Construction, pp. 219-233, Palo Alto, California, June 1986. Association for Computing Machinery. ACM SIGPLAN Notices, 21:7, July 1986. ISBN 0-89791-197-0. [Landin, 1964] Landin, Peter J. The mechanical evaluation of expressions. Computer Journal, 6:4, 1964. [Landin, 1965] Landin, Peter J. A correspondence between ALGOL 60 and Church's lambda-notation. Communications of the ACM, 8:2-3, February-March 1965. [Lisp Conference, 1980] Republished by Association for Computing Machinery. Conference Record of the 1980 LISP Conference, Stanford, California, August 1980. [Malachi, 1984] Malachi, Yonathan, Zohar Manna, and Richard Waldinger. TABLOG: The deductive-tableau programming language. In [ACM LFP, 1984], pp. 323-330. [Marti, 1979] Marti, J., A. C. Hearn, M. L. Griss, and C. Griss. Standard lisp report. ACM SIGPLAN Notices, 14:10, pp. 48-68, October 1979. [Mathlab Group, 1977] Mathlab Group, The. MACSYMA Reference Manual (Version Nine). MIT Laboratory for Computer Science, Cambridge, Massachusetts, 1977. [McAllester, 1978] McAllester, David A. A Three Valued Truth Maintenance System. AI Memo 473, MIT Artificial Intelligence Laboratory, Cambridge, Massachusetts, May 1978. [McCarthy, 1962] McCarthy, John, Paul W. Abrahams, Daniel J. Edwards, Timothy P. Hart, , and Michael I. Levin. LISP 1.5 Programmer's Manual. MIT Press, Cambridge, Massachusetts, 1962. [McCarthy, 1980] McCarthy, John. Lisp: Notes on its past and future. In [Lisp Conference, 1980], pp. v-viii. [McCarthy, 1981] McCarthy, John. History of LISP. In Wexelblat, Richard L., ed., History of Programming Languages, ACM Monograph Series, chapter IV, pp. 173-197. Academic Press, New York, 1981. ISBN 0-12-745040-8. [McDermott, 1974] McDermott, Drew V., and Gerald Jay Sussman. The CONNIVER Reference Manual. AI Memo 295a, MIT Artificial Intelligence Laboratory, Cambridge, Massachusetts, January 1974. [McDermott, 1980] McDermott, Drew. An efficient environment allocation scheme in an interpreter for a lexically-scoped LISP. In [Lisp Conference, 1980], pp. 154-162. [Mellish, 1984] Mellish, C., and S. Hardy. Integrating Prolog in the POPLOG environment. In [Campbell, 1984], pp. 147-162. [Miller, 1987] Miller, James Slocum. MultiScheme: A Parallel Processing System Based on MIT Scheme. PhD thesis, Massachusetts Institute of Technology, Cambridge, Massachusetts, August 1987. [MIT RLE, 1962a] MIT Research Laboratory of Electronics. MIT Press, Cambridge, Massachusetts. COMIT Programmers Reference Manual, June 1962. [MIT RLE, 1962b] MIT Research Laboratory of Electronics. MIT Press, Cambridge, Massachusetts. An Introduction to COMIT Programming, June 1962. [Moon, April 1974] Moon, David A. MacLISP Reference Manual. MIT Project MAC, Cambridge, Massachusetts, April 1974. [Moon, 1984] Moon, David A. Garbage collection in a large Lisp system. In [ACM LFP, 1984], pp. 235-246. [Moon, 1986] Moon, David A. Object-oriented programming with flavors. In [ACM OOPSLA, 1986], pp. 1-8. [Moore, 1976] Moore, J. Strother II. The InterLISP Virtual Machine specification. Technical Report CSL 76-5, Xerox Palo Alto Research Center, Palo Alto, California, September 1976. [Naur, 1963] Naur, Peter (ed.), et al. Revised report on the algorithmic language ALGOL 60. Communications of the ACM, 6:1, pp. 1-20, January 1963. [Okuno, 1984] Okuno, Hiroshi G., Ikuo Takeuchi, Nobuyasu Osato, Yasushi Hibino, and Kazufumi Watanabe. TAO: A fast interpreter-centered Lisp system on Lisp machine ELIS. In [ACM LFP, 1984], pp. 140-149. [Organick, 1972] Organick, Elliot I. The Multics System: An Examination of Its Structure. MIT Press, Cambridge, Massachusetts, 1972. [Padget, 1986] Padget, Julian, et al. Desiderata for the standardization of Lisp. In [ACM LFP, 1986], pp. 54-66. [PDP-6 Lisp, 1967] PDP-6 LISP (LISP 1.6). AI Memo 116, MIT Project MAC, Cambridge, Massachusetts, January 1967. Revised as Memo 116A, April 1967. レポートには著者の名前が記載されていないが、Jeffrey P. Golden [Golden, 1970]はJon L Whiteの作だとしている。 [Pitman, 1980] Pitman, Kent M. Special forms in Lisp. In [Lisp Conference, 1980], pp. 179-187. [Pitman, 1983] Pitman, Kent M. The Revised MacLISP Manual. MIT/LCS/TR 295, MIT Laboratory for Computer Science, Cambridge, Massachusetts, May 1983. [Pratt, 1973] Pratt, Vaughan R. Top down operator precedence. In Proc. ACM Symposium on Principles of Programming Languages, pp. 41-51, Boston, October 1973. ACM SIGACT and SIGPLAN, Association for Computing Machinery. [Pratt, 1976] Pratt, Vaughan R. CGOL: An Alternative External Representation for LISP Users. AI Working Paper 121, MIT Artificial Intelligence Laboratory, Cambridge, Massachusetts, March 1976. [Quam, 1972] Quam, Lynn H., and Whitfield Diffie. Stanford LISP 1.6 Manual. SAIL Operating Note 28.6, Stanford Artificial Intelligence Laboratory, Stanford, California, 1972. [Raymond, 1991] Raymond, Eric, ed. The New Hacker's Dictionary. MIT Press, Cambridge, Massachusetts, 1991. [Rees, 1982] Rees, Jonathan A., and Norman I. Adams IV. T: A dialect of Lisp; or, LAMBDA: The ultimate software tool. In [ACM LFP, 1982], pp. 114-122. [Rees, 1986] Rees, Jonathan, William Clinger, et al. The revised^3 report on the algorithmic language Scheme. ACM SIGPLAN Notices, 21:12, pp. 37-79, December 1986. [Reynolds, 1972] Reynolds, John C. definitional interpreters for higher order programming languages. In Proc. ACM National Conference, pp. 717-740, Boston, August 1972. Association for Computing Machinery. [Robinson, 1982] Robinson, J. A., and E. E. Sibert. LOGLISP: Motivation, design, and implementation. In [Clark, 1982], pp. 299-313. [Roylance, 1988] Roylance, Gerald. Expressing mathematical subroutines constructively. In [ACM LFP, 1988], pp. 8-13. [Rudloe, 1962] Rudloe, H. Tape Editor. Program Write-up BBN-101, Bolt Beranek and Newman Inc., Cambridge, Massachusetts, January 1962. [Sabot, 1988] Sabot, Gary W. The Paralation Model: Architecture-Independent Parallel Programming. MIT Press, Cambridge, Massachusetts, 1988. ISBN 0-262-19277-2. [Saunders, 1985a] Saunders, Robert A. The LISP listing for the Q-32 compiler, and some samples. In [Berkeley, 1985], pp. 290-317. [Saunders, 1985b] Saunders, Robert A. The LISP system for the Q-32 computer. In [Berkeley, 1985], pp. 220-238. [Shaw, 1981] Shaw, Mary, Wm. A. Wulf, and Ralph L. London. Abstraction and verification in Alphard: Iteration and generators. In Shaw, Mary, ed., ALPHARD: Form and Content, chapter 3, pp. 73-116. Springer-Verlag, New York, 1981. ISBN 0-387-90663-0. [Smith, 1970] Smith, David Canfield. MLISP. Technical Report AIM-135, Stanford Artificial Intelligence Project, October 1970. [Sobalvarro, 1988] Sobalvarro, Patrick G. A Lifetime-based Garbage Collector for LISP Systems on General-Purpose Computers. Bachelor's Thesis, Massachusetts Institute of Technology, Cambridge, Massachusetts, September 1988. [Smith, 1973] Smith, David Canfield, and Horace J. Enea. Backtracking in MLISP2: An efficient backtracking method for LISP. In [IJCAI, 1973], pp. 677-685. [Stallman, 1976] Stallman, Richard M., and Gerald Jay Sussman. Forward Reasoning and Dependency-Directed Backtracking in a System for Computer-Aided Circuit Analysis. AI Memo 380, MIT Artificial Intelligence Laboratory, Cambridge, Massachusetts, September 1976. Also in i[ArtificialIntelligence]b[9] (1977), 135-196. [Steele, 1976a] Steele, Guy Lewis, Jr. LAMBDA: The Ultimate Declarative. AI Memo 379, MIT Artificial Intelligence Laboratory, Cambridge, Massachusetts, November 1976. [Steele, 1976b] Steele, Guy Lewis, Jr., and Gerald Jay Sussman. LAMBDA: The Ultimate Imperative. AI Memo 353, MIT Artificial Intelligence Laboratory, Cambridge, Massachusetts, March 1976. [Steele, 1977a] Steele, Guy L., Jr. Macaroni is better than spaghetti. In Proceedings of the Artificial Intelligence and Programming Languages Conference, pp. 60-66, Rochester, New York, August 1977. ACM SIGPLAN and SIGART. Proceedings published as ACM SIGPLAN Notices 12, 8 (August 1977) and as ACM SIGART Newsletter 64 (August 1977). [Steele, 1977b] Steele, Guy Lewis, Jr. Compiler optimization based on viewing LAMBDA as rename plus goto. Master's thesis, Massachusetts Institute of Technology, May 1977. [Steele, 1978a]として出版された。 [Steele, 1977c] Steele, Guy Lewis, Jr. Data representations in PDP-10 MacLISP. In Proceedings of the 1977 MACSYMA Users' Conference, pp. 203-214, Washington, D.C., July 1977. NASA scientific and Technical Information Office. [Steele, 1977d] Steele, Guy Lewis, Jr. Debunking the `expensive procedure call' myth; or, Procedure call implementations considered harmful; or, LAMBDA: The ultimate GOTO. In Proceedings of the ACM National Conference, pp. 153-162, Seattle, October 1977. Association for Computing Machinery. [Steele, 1977e] Steele, Guy Lewis, Jr. Fast arithmetic in maclisp. In Proceedings of the 1977 MACSYMA Users' Conference, pp. 215-224, Washington, D.C., July 1977. NASA scientific and Technical Information Office. [Steele, 1978a] Steele, Guy Lewis, Jr. RABBIT: A Compiler for SCHEME (A Study in Compiler Optimization). Technical Report 474, MIT Artificial Intelligence Laboratory, May 1978. これは著者の修士論文 [Steele, 1977b]の改訂版である。 [Steele, 1978b] Steele, Guy Lewis, Jr., and Gerald Jay Sussman. The Art of the Interpreter; or, The Modularity Complex (Parts Zero, One, and Two). AI Memo 453, MIT Artificial Intelligence Laboratory, Cambridge, Massachusetts, May 1978. [Steele, 1978c] Steele, Guy Lewis, Jr., and Gerald Jay Sussman. The Revised Report on SCHEME: A Dialect of LISP. AI Memo 452, MIT Artificial Intelligence Laboratory, Cambridge, Massachusetts, January 1978. [Steele, 1979] Steele, Guy Lewis, Jr., and Gerald Jay Sussman. Constraints. In Proceedings of the APL 79 Conference, pp. 208-225, Rochester, New York, June 1979. ACM SIGPLAN STAPL. APL Quote Quad, 9:4, June 1979. [Steele, 1980] Steele, Guy Lewis, Jr., and Gerald Jay Sussman. The dream of a lifetime: A lazy variable extent mechanism. In [Lisp Conference, 1980], pp. 163-172. [Steele, 1982] Steele, Jr., Guy L. An overview of Common Lisp. In [ACM LFP, 1982], pp. 98-107. [Steele, 1984] Steele, Guy L., Jr., Scott E. Fahlman, Richard P. Gabriel, David A. Moon, and Daniel L. Weinreb. Common Lisp: The Language. Digital Press, Burlington, Massachusetts, 1984. [Steele, 1986] Steele, Guy L., Jr., and W. Daniel Hillis. Connection Machine Lisp: fine-grained parallel symbolic processing. In [ACM LFP, 1986], pp. 279-297. [Steele, 1990a] Steele, Jr., Guy L. Making asynchronous parallelism safe for the world. In Proc. Seventeenth Annual ACM Symposium on Principles of Programming Languages, pp. 218-231, San Francisco, January 1990. ACM SIGACT/SIGPLAN, Association for Computing Machinery. ISBN 0-89791-343-4. [Steele, 1990b] Steele, Jr., Guy L., and Jon L White. How to print floating-point numbers accurately. In Proc. 1990 ACM SIGPLAN '90 Conference on Programming Language Design and Implementation, pp. 112-126, White Plains, New York, June 1990. Association for Computing Machinery. Proceedings published as ACM SIGPLAN Notices 25, 6 (June 1990). [Steele, 1990c] Steele, Guy L., Jr., Scott E. Fahlman, Richard P. Gabriel, David A. Moon, Daniel L. Weinreb, Daniel G. Bobrow, Linda G. DeMichiel, Sonya E. Keene, Gregor Kiczales, Crispin Perdue, Kent M. Pitman, Richard C. Waters, and Jon L White. Common Lisp: The Language (Second Edition). Digital Press, Bedford, Massachusetts, 1990. [Sussman, 1971] Sussman, Gerald Jay, Terry Winograd, and Eugene Charniak. Micro-PLANNER Reference Manual. AI Memo 203A, MIT Artificial Intelligence Laboratory, Cambridge, Massachusetts, December 1971. [Sussman, 1972a] Sussman, Gerald Jay, and Drew Vincent McDermott. From PLANNER to CONNIVER - A genetic approach. In Proc. 1972 Fall Joint Computer Conference, pp. 1171-1179, Montvale, New Jersey, August 1972. AFIPS Press. これは、Why Conniving is Better than Planningの 出版された版である。 [Sussman, 1972b] Sussman, Gerald Jay, and Drew Vincent McDermott. Why Conniving is Better than Planning. AI Memo 255A, MIT Artificial Intelligence Laboratory, Cambridge, Massachusetts, April 1972. [Sussman, 1975a] Sussman, Gerald Jay, and Richard M Stallman. Heuristic Techniques in Computer-Aided Circuit Analysis. AI Memo 328, MIT Artificial Intelligence Laboratory, Cambridge, Massachusetts, March 1975. [Sussman, 1975b] Sussman, Gerald Jay, and J Steele, Guy Lewis. SCHEME: An Interpreter for Extended Lambda Calculus. AI Memo 349, MIT Artificial Intelligence Laboratory, Cambridge, Massachusetts, December 1975. [Sussman, 1988] Sussman, Gerald Jay, and Matthew Halfant. Abstraction in numerical methods. In [ACM LFP, 1988], pp. 1-7. [Swanson, 1988] Swanson, Mark R., Robert R. Kessler, and Gary Lindstrom. An implementation of Portable Standard Lisp on the BBN Butterfly. In [ACM LFP, 1988], pp. 132-142. [Swinehart, 1972] Swinehart, D. C., and R. F. Sproull. SAIL. SAIL Operating Note 57.2, Stanford Artificial Intelligence Laboratory, Stanford, California, 1972. [Symbolics, 1985] Symbolics, Inc., Cambridge, Massachusetts. Reference Guide to Symbolics-Lisp, March 1985. [Takeuchi, 1983] Takeuchi, Ikuo, Hiroshi Okuno, and Nobuyasu Ohsato. TAO: A harmonic mean of Lisp, Prolog, and Smalltalk. ACM SIGPLAN Notices, 18:7, pp. 65-74, July 1983. [Teitelman, 1966] Teitelman, Warren. PILOT: A Step toward Man-Computer Symbiosis. Technical Report MAC-TR-32, MIT Project MAC, September 1966. Ph.D. thesis. [Teitelman, 1971] Teitelman, W., D. G. Bobrow, A. K. Hartley, and D. L. Murphy. BBN-LISP: TENEX Reference Manual. Bolt Beranek and Newman Inc., Cambridge, Massachusetts, 1971. [Teitelman, 1973] Teitelman, Warren. CLISP: Conversational LISP. In [IJCAI, 1973], pp. 686-690. [Teitelman, 1974] Teitelman, Warren, et al. InterLISP Reference Manual. Xerox Palo Alto Research Center, Palo Alto, California, 1974. First revision. [Teitelman, 1978] Teitelman, Warren, et al. InterLISP Reference Manual. Xerox Palo Alto Research Center, Palo Alto, California, October 1978. Third revision. [Tesler, 1973] Tesler, Lawrence G., Horace J. Enea, and David C. Smith. The LISP70 pattern matching system. In [IJCAI, 1973], pp. 671-676. [Thacker, 1982] Thacker, C. P., E. M. McCreight, B. W. Lampson, R. F. Sproull, and D. R. Boggs. Alto: A personal computer. In Siewiorek, Daniel P., C. Gordon Bell, and Allen Newell, eds., Computer Structures: Principles and Examples, Computer Science Series, chapter 33, pp. 549-572. McGraw-Hill, New York, 1982. ISBN 0-07-057302-6. [Travis, 1977] Travis, Larry, Masahiro Honda, Richard LeBlanc, and Stephen Zeigler. Design rationale for TELOS, a PASCAL-based AI language. In Proc. Symposium on Artificial Intelligence and Programming Languages, pp. 67-76, Rochester, New York, August 1977. Association for Computing Machinery. [Vuillemin, 1988] Vuillemin, Jean. Exact real computer arithmetic with continued fractions. In [ACM LFP, 1988], pp. 14-27. [Wand, 1977] Wand, Mitchell, and Daniel P. Friedman. Compiling Lambda Expressions Using Continuations and Factorization. Technical Report 55, Indiana University, July 1977. [Waters, 1984] Waters, Richard C. Expressional loops. In Proc. Eleventh Annual ACM Symposium on Principles of Programming Languages, pp. 1-10, Salt Lake City, Utah, January 1984. ACM SIGACT/SIGPLAN, Association for Computing Machinery. ISBN 0-89791-125-3. [Waters, 1989a] Waters, Richard C. Optimization of Series Expressions, Part I: User's Manual for the Series Macro Package. AI Memo 1082, MIT Artificial Intelligence Laboratory, Cambridge, Massachusetts, January 1989. [Waters, 1989b] Waters, Richard C. Optimization of Series Expressions, Part II: Overview of the Theory and Implementation. AI Memo 1083, MIT Artificial Intelligence Laboratory, Cambridge, Massachusetts, January 1989. [Wegbreit, 1970] Wegbreit, Ben. Studies in Extensible Programming Languages. PhD thesis, Harvard University, Cambridge, Massachusetts, 1970. [Wegbreit, 1971] Wegbreit, Ben. The ECL programming system. In Proc. 1971 Fall Joint Computer Conference, pp. 253-262, Montvale, New Jersey, August 1971. AFIPS Press. [Wegbreit, 1972] Wegbreit, Ben, Ben Brosgol, Glenn Holloway, Charles Prenner, and Jay Spitzen. ECL Programmer's Manual. Technical Report 21-72, Harvard University Center for Research in Computing Technology, Cambridge, Massachusetts, September 1972. [Wegbreit, 1974] Wegbreit, Ben, Glenn Holloway, Jay Spitzen, and Judy Townley. ECL Programmer's Manual. Technical Report 23-74, Harvard University Center for Research in Computing Technology, Cambridge, Massachusetts, December 1974. [Weinreb, November 1978] Weinreb, Daniel, and David Moon. LISP Machine Manual, Preliminary Version. MIT Artificial Intelligence Laboratory, Cambridge, Massachusetts, November 1978. [Weinreb, March 1981] Weinreb, Daniel, and David Moon. LISP Machine Manual, Third Edition. MIT Artificial Intelligence Laboratory, Cambridge, Massachusetts, March 1981. [White, 1980] White, Jon L. Address/memory management for a gigantic LISP environment; or, GC considered harmful. In [Lisp Conference, 1980], pp. 119-127. [White, 1969-1982] White, Jon L, et al. LISP ARCHIV. On-line archive of MacLisp release notes., 1969-1982. [White, 1986] White, Jon L. Reconfigurable, retargetable bignums: A case study in efficient, portable Lisp system building. In [ACM LFP, 1986], pp. 174-191. [Wulf, 1971] Wulf, W.A., D.B. Russell, and A.N. Habermann. Bliss: A language for systems programming. Communications of the ACM, 14:12, pp. 780-790, December 1971. [Wulf, 1975] Wulf, William, Richard K. Johnsson, Charles B. Weinstock, Steven O. Hobbs, and Charles M. Geschke. The Design of an Optimizing Compiler, volume 2 of Programming Language Series. American Elsevier, New York, 1975. ISBN 0-444-00164-6. [Yngve, 1972] Yngve, Victor H. Computer Programming with COMIT II. MIT Press, Reading, Massachusetts, 1972. ISBN 0-262-74007-9.