前書き

教育者、将軍、栄養士、精神分析医、そして両親は、計画を立て(program)ます。軍隊や学生は計画によって動いていますし、計画によって動いている社会もあります。大きな課題に取り組むときにはいくつもの計画を使いますが、それらのほとんどは問題に取り組む中で生まれるものです。それらの計画には、そのとき取り組んでいる課題に特化しているように見える問題があふれています。計画を立てるということ自体を知的な活動として理解するためには、コンピュータプログラミングに目を向ける必要があります。コンピュータプログラムを読み書きする必要があります---それも、大量に。何のプログラムか、どういう応用のためかというところはあまり重要ではありません。重要なのは、それらがどのようにふるまい、またより大きなプログラムを作る中でそれらがどれだけスムーズにほかのプログラムと協調できるかということです。プログラマは、部品の完全性と、組み合わせたものの妥当性の、両方を追求しなければいけません。この本では、“プログラム”というのは、Lispのある方言で書かれた、デジタルコンピュータ上で実行されることを前提としたプログラムの作成・実行・研究に焦点を当てています。Lispを使うことは、プログラムの記述について制約を加えるだけで、何をプログラムするかを制約するものではありません。

この本の主題について考えるうえで、3つの事象を考えることになります。人間の心、コンピュータプログラムの集合、そしてコンピュータです。コンピュータプログラムはすべて、実際のプロセスや精神的なプロセスのモデルであり、人間の心の中で生まれるものです。これらのプロセスは、人間の経験と思考から浮かび上がってくるもので、数はとても多く、細かいところまで入り組んでいて、いつでも部分的に理解することしかできません。それらがコンピュータプログラムとして永遠に満足できるようにモデル化されるなんていうことは、めったにありません。ですから、私たちのプログラムは、注意深く工夫されたばらばらの記号の集合であり、絡まり合う関数の組み合わせでありながらも、絶えず進化していきます。私たちのモデルに対する理解が深まったり、広がったり、一般化したりするたびに、私たちはプログラムに手を加えていきます。最終的に、モデルは準安定状態に達し、それは私たちが取り組む別のモデルの中に位置を占めることになります。コンピュータプログラミングに関する興奮の源は、プログラムとして表現されたメカニズムが私たちの心の中とコンピュータ上で絶え間なく広がっていくことと、またそれが生み出す知覚の爆発です。芸術が私たちの夢を解釈するものだとすると、コンピュータは夢を、プログラムという形で実行するものなのです!

コンピュータは強力ですが、厳しい親方でもあります。プログラムは正しくなければならず、伝えたいことは細かいところまで正確に伝えなければいけません。ほかのすべての記号的な活動と同じく、プログラムが真であることは論証によって知ることができます。Lispはそれ自身、意味論(これもまたモデルです)を割り当てることができ、そしてプログラムの仕様が、例えば述語論理などによって決められるのであれば、論理学の証明方法によって、容認可能な正確性の論証をすることができます。残念ながら、プログラムが大きく複雑になるにつれ(いつもそうなるのですが)、仕様自体の妥当性、一貫性、正しさが疑わしいものになっていきます。そのため、完全な形式的な正しさの論証というものが大きなプログラムについてくるということはめったにありません。大きなプログラムは小さなものから成長していくものなので、正しさについて確信を持てるような標準的なプログラム構造(これをイディオムと呼びます)の武器庫を作り上げ、確立された組織化技術によってより大きな構造に組み立てていく方法を学ぶことが決定的に重要になります。この本では、それらの技術について詳細に扱っていきます。それらを理解することは、プロメテウスのような創造的な営みであるプログラミングという分野に加わるためには不可欠なことです。何よりも、強力な組織化の技術を発見し身につけていくことによって、大規模で重要なプログラムを書くにあたって必要となる能力を育てることができます。また逆に、大規模なプログラムを書くことは負担がとても大きいということもあり、何とか新しい手法を発明して、大規模なプログラムに組み込む関数や実装の量を減らすことができないかと考えていくことになります。

プログラムとは違って、コンピュータは物理法則に従わなければなりません。もし素早く---状態遷移あたり数ナノ秒といったレベルで---動作したければ、電子をほんの短い距離(せいぜい1121{1\over2} フィートだけ)しか運ぶことができません。空間的にぎっしり詰め込まれた膨大な数のデバイスが発する熱は、取り除く必要があります。高機能性とデバイス密度のバランスを取りながら、精緻な工学的技法が発展してきました。いずれにせよ、ハードウェアは私たちがプログラムしようとしているレベルよりも基礎的なレベルで動いています。私たちのLispのプログラムを“機械の”プログラムに変換する処理は、それ自身が抽象的なモデルで、それは私たちがプログラムするものです。その研究と作成は、どんなモデルをプログラムするときにも関わってくるような組織的プログラムについて、多くの洞察を与えてくれます。もちろん、コンピュータそれ自身もそのようにモデル化されています。考えてみてください。一番小さい物理的なスイッチング素子は量子力学によってモデル化され、量子力学は微分方程式によって記述され、微分方程式の詳細なふるまいは数値近似によって表され、数値近似はコンピュータプログラムによって表現され、そのコンピュータプログラムはコンピュータによって実行され、そのコンピュータを構成する素子は…!

3つの焦点を別々に設定することは、単なる方法上の便利さのためだけではありません。よく「すべては頭の中のことだ」と言われますが、このように論理的に分けることによって、これらの焦点の間の記号的通信を促進できます。人間の経験の中で、これら3つの豊かさ、生命力、潜在力を超えるものは、人生そのものの発展ぐらいです。これらの焦点の間の関係は、せいぜい準安定状態です。コンピュータの容量の大きさや速さは、これで十分となることは決してありません。ハードウェア技術の進歩のたびに、より大きなプログラミングの取り組み、新しい組織化原則、そして抽象モデルの発展が引き起こされます。読者は、定期的に“どこに向かっているんだ? どこに向かっているんだ?”と自問しなければなりません。---でも、あまり問いすぎないようにしましょう。そうでないと、ほろ苦い哲学的な便秘のたに、プログラミングの楽しさを見逃してしまうことになります。

私たちが書くプログラムの中で、一部のもの(しかし、決して十分にはならない)は、並べ替え、数列の最大値を見つける、素数性判定、平方根の計算といった、精密な数学的な関数を実行します。そのようなプログラムはアルゴリズムと呼ばれ、その最適なふるまいについては多くのこと(特に、実行時間とデータストレージの必要量という二つのパラメータについて)が知られています。プログラマは、よいアルゴリズムとイディオムを身につけなければなりません。プログラムの中には厳密な仕様が記述しにくいものもありますが、プログラマとしては責任を持ってパフォーマンスを推定し、また常に改善しようとしなければなりません。

Lispは、“生き残ったもの”です。約四半世紀にわたって使われてきています。活発なプログラミング言語の中で、これより長い時間を生きてきたものはFortranだけです。どちらの言語も、重要な応用領域でのプログラミングの必要性を支えてきています。Fortranは科学計算と工学計算を支え、Lispは人工知能を支えてきました。この二つの分野は今でも重要であり続け、これらの分野のプログラマはLispとFortranという二つの言語に力を注いでいるので、少なくとももうあと四半世紀の間活発に使われる言語であり続けるということは十分ありうることです。

Lispは変化します。このテキストで使っているScheme方言は、オリジナルのLispから進化してきたもので、いくつかの重要な点で異なっています。例えば、変数束縛のための静的スコーピングや、関数が関数を値として返すことを許可することなどです。構文的な構造において、SchemeはAlgol 60に似ています。その近さは、Schemeと初期のLispとの近さと同じ程度です。Algol 60は、もう活発な言語になることはないでしょうが、SchemeとPascalの遺伝子の中に生き続けています。これら二つの言語ほど、かけ離れた文化に取り囲まれ、その流通貨幣となっているような二つの言語というのもなかなかないでしょう。Pascalはピラミッドを建てるためのものです。雄大で、息をのむような、静的な構造物で、軍隊が重い石を運び、所定の位置に押しこむことによって作られています。Lispは有機体を作るためのものです。雄大で、息をのむような、動的な構造物で、小さなチームが無数のより単純な揺れ動く有機物を所定の位置に入れることによって作られています。どちらの場合にも、組織化のための原則は同じですが、ひとつだけ非常に重要な違いがあります。個々のLispプログラマに委ねられたエクスポート可能な関数は、Pascal企業の中で見つけられるものより桁違いに多いのです。Lispのプログラムは、本来目的としていたアプリケーションを超えた有用性を持つ関数でライブラリをいっぱいにします。そのように有用性が増加していく背景には、リストというLispのネイティブデータ構造の存在があります。リストの単純な構造と自然な適用可能性は、驚くほど普遍的な関数という形で表れてきます。Pascalでは、宣言可能なデータ構造の多さが関数の専門化を引き起こし、気軽な連携は禁じられ、ペナルティを与えられるものとなります。ひとつのデータ構造を扱う100の関数があるほうが、10のデータ構造を扱う10の関数があるのよりもよいのです。結果として、ピラミッドは千年もの間変化せずに存在し続けなければならないのに対し、有機体は存在する限り進化し続けなければなりません。進化を止めるということは滅びることを意味します。

この違いをはっきり知るためには、この本の中での教材と練習問題の扱いを、何でもいいのでPascalを使った入門テキストと比べてみてください。このテキストはMITでしか消化できない、MITに固有の種族のためのものだとかいった妄想は抱かないでください。このテキストは、真面目なLispのプログラミングの本はどのようなものでなければいけないかというところを形にしたものであり、学生が誰であるか、どこで使われるかは関係ありません。

ひとつ気をつけておいていただきたいのは、この本はプログラミングに関するテキストだということです。ほとんどのLispの本は人工知能に使うための準備となっていますが、この本は違います。いずれにしても、対象となるシステムが大きくなるにつれ、ソフトウェア工学と人工知能に関わる重要なプログラミング上の課題は融合していく傾向にあります。まさにそのために、人工知能以外の領域でも、Lispに対してこれほどの関心が向けられているのです。

その目的とするところから予想できる通り、人工知能の研究は数多くの重要なプログラミングの問題を生み出しています。ほかのプログラミング分野であれば、このような大量の問題に対しては新しい言語が生み出されるところです。実際に、非常に大きなプログラミングのタスクにおいて、組織化のために便利な方法のひとつは、新しい言語を発明して、タスクモジュールの中に通信を閉じ込め、コントロールするということです。これらの言語は、私たち人間が頻繁にやりとりを行うシステムの周辺部に近づくにつれて、単純でなくなっていく傾向があります。その結果、そのようなシステムでは、複雑な言語処理の機能が何回も繰り返し実装されることになります。Lispは、非常に単純なシンタックスとセマンティクスを持つため、パージングは初歩的なタスクとして扱うことができます。ですので、パージング技術はLispのプログラムの中でほとんど何の役割も果たしません。また、大きなLispのシステムが成長し変化していく中で、言語処理系の構築がその成長速度の妨げになることはめったにありません。最後になりますが、このシンタックスとセマンティクスの単純さこそが、すべてのLispプログラマが付き合うことになる重荷と自由の源泉になっているのです。数行以上のLispプログラムを書こうとすると、必ず自由に使える関数でいっぱいになります。発明し、組み込み(fit)ましょう。かんしゃくを起こし(have fits)、再発明しましょう! 括弧のネストの中に自分の考えを書いていくLispプログラマに乾杯。

Alan J. Perlis

New Haven, Connecticut

results matching ""

    No results matching ""