Lispのアイデア

Lispと聞くと、冷蔵庫のような大きいサイズのコンピュータや、大文字のアルファベット文字列や括弧の並びといったような過去の時代のことが頭に浮かびます。そう、非常に多くの括弧。何故、オブジェクト指向プログラミングの作成者たちは、そんなにもLispのアイデアに魅了されるのでしょうか。そしてまた、アイデアとされるプログラミング言語というものは、どうやったら説明できるでしょうか。こうしたことを教えてくれなかったコンピュータ科学の教育を責めるべきでしょうか。

Lispは、John McCarthyが書いたRecursive Functions of Symbolic Expressions and Their Interpretation by Machines, Part Iという論文によって、初めて世界に登場しました。その中で、McCarthyはプログラミングに新しい多くのアイデアを導入しています。例えば、条件式(そう、if/then/elseです)や変数に複数の文字(時には単語やフレーズの場合もあります)を使うといったことです(数学ではいまだに1文字です)。皆さんがどのプログラミング言語を好んでいようと、この2つの特徴についてはJohn McCarthyに負っています。しかし、それだけではありません。Lisp自体の定義には、更に深いアイデアが潜んでいるのです。

John McCarthy

彼は、条件式と共に5種類の基本演算(atomeqconscar、およびcdr)を定義しました。これに関数を定義する方法も想定した上で、それらを使って、それ自身で定義された、プログラミング言語全体を定義しました。別の言葉で説明すると、John McCarthyは6つの簡単な事柄を機械語で書き、それらを組み合わせてプログラミング言語を作ったのでした。それ以前に登場していた唯一の高級プログラミング言語といえば、その開発に18人年の歳月を要したFortranでした。Fortranは大きな成果でしたが、Lispは大きなアイデアだったと言えるでしょう。

その大変優れたアイデアについて少し紐解いてみましょう。

ブートストラッピングの材料が非常に少ない

これら6つのものが、(インタープリタによって)解釈が可能なシンボルのリストを提供し、他のシステムに簡単に移植できる非常に小さな”カーネル”を定義します。これは小さな合意の”定点”とでも言えるもので、この他の全ての意味は、それらの観点から定義されます。

言語は、それ自体がインタプリタという観点で定義される

これは、言語が万能であるということの構成的な証明です。チューリング完全のアイデアには、実際には2つの部分があります。1つ目は、計算可能なものを計算できることです。これについては、ほとんどのプログラミング言語がクリアしているでしょう(再帰関数を持つLispも該当します)。しかし、2つ目は少し特殊です。チューリングマシンが万能と見なされるには、他のチューリングマシンを解釈できなければなりません。Lispについては、万能チューリングマシン同様、当初からそれ自身がインタプリタとして定義されており、それ自身のコードを解釈できるので万能言語です。JavaScriptでは恐らくJavascriptインタプリタを書くことはできますが、それは自身のために書かれているわけではありません。

言語内の式の意味が、インタプリタによって定義される

式に異なる意味を割り当てた独自のインタプリタを書くことができます。これはAlan Kayの”遅延バインディング”の概念です。プログラミングについての知識が乏しい中で、あまりにも多くの前提を言語の基盤に組み込むのは、ある意味で間違いとも言えます。より習熟していく中で、全てを捨て去ることなく、前提をスワップできるシステムが望まれたのです。

式がデータ構造として記述される

式は、再帰的なリンクトリストとして記述されます。5種類の基本を押さえるだけで、これらのデータ構造を使い、解釈することが可能です。

ほとんどのLispシステムでは、毎回式を解釈する代わりに機械語にコンパイルするといったような現実的な妥協を行っていますが、それでもLisperは、この非常に柔軟な”カーネル”で快適に作業しています。以下に挙げるのは、Lispのアイデアから直接導き出されるLispのいくつかの機能です。

マクロ

マクロは、コードを引数に取りコードを返す関数です。コードの変換器と言えるでしょう。言語の表現力を拡張し、コンパイル時に計算を実行できるようにします。

データ駆動型プログラミング

Lisperは、自分が作成する新しい言語のインタプリタをLispで書くことがよくあります。新しい言語のためにLispのブートストラッピングを再制定するのです。
これらはある意味で、DSL(ドメイン特化言語)と見なすことができます。

プログラミング言語の実験

Lispはそれ自身のインタプリタを書くように作られているので、言語の代替セマンティクスを試すのに最適です。

私たちはプログラミングが歩んできた道を忘れがちです。現在最も偉大だとされている言語は絶え間ない変化を繰り返していますし、今日持てはやされている言語も15年後には消えてしまうでしょう。しかしLispというアイデアは生き残ります。現時点で最も有望な、その生まれ変わりはJVMとJavaScriptで動作するClojureです。

しかし、以下のように、Lispのアイデアは、あなたの好みの言語にも根付いています。

REPL

REPLとはRead-Eval-Print-Loop(対話型評価環境)の略で、それを定義した4つのLisp構造体の名前でもあります。あなたのお気に入りの言語が、コードを入力して実行させることのできるインタラクティブなプロンプトを持っているとしたら、それはLispに由来しているのです。

再帰関数

1960年のコンピュータ科学者たちは、再帰関数が可能であることは分かっていましたが、非常にコストがかかると思っていました。当時のもう1つの主要言語であったFortranにも、その頃、再帰関数はありませんでした。しかし今や、再帰関数がないと話にもなりません。

ガベージコレクション

Lispはガベージコレクション(GC)を持つ最初の言語でした。言語がテンポラリオブジェクトを数多く作成し、かつそれらが長い間生存することが、LispにGCが必要となった主な要因です。

条件式

そう、条件式を発明したのはJohn McCarthyなのです。彼はAlgolに条件式を追加するようAlgol開発プロジェクトに働きかけました。今日では、ほとんどの言語がそこから条件式を得ています。

複数文字から成る変数名

前述しましたが、ここでもう一度繰り返します:McCarthyの登場以前、プログラマは数学の導きに従い、1文字の変数名を使用していました。

リテラルデータの構造

自分のお気に入りの言語の構文で、配列やマップを直接記述することができますか? 括弧()を使ってそれを最初にやったのもLispなのです。

こんなAlan Kayの言葉があります。

コンピュータ科学の学位を取得した学生のほとんどは、Lispの意義深さを理解していない。Lispはコンピュータ科学において、最も重要なアイデアだ。

私自身、卒業時にはその意義深さを理解してはいませんでした。卒業してからのたくさんの読書と探求により、やっとコンピュータ科学において適切な教養を得ることができたと実感しています。ニュースレターをご覧いただければ、私が学んだ内容を確認いただくことが可能です。学べば学ぶほど、40年以上前に発表されたものの奥行きと幅広さに魅了されるばかりです。

コンピュータ科学、プログラミングの歴史、あるいはLispのアイデアの数々に興味があるなら、ぜひPurelyFunctional.tv Newsletterをチェックしてみてください。Lispと関数型プログラミングの歴史、現在、未来について考察した週刊のニュースレターです。