2006-06-19
■ [prog] Lispはなぜ凄いのか
KMCでは、毎週のミーティングのときに誰か一人が15〜30分程度の発表(「講座」という)を行う習慣がある。 今日は僕がLispに関する話をしたので、せっかくだからその内容をメモっておこうと思う。
内容は「Lispはスゴいという話をたまに聞くけど、何が凄いの?」という話。 Lispの凄いところは2つあって、1つは「動的」「GC」「高階関数」など最近プログラミング言語に搭載されるようになった機能を、'59年に既に備えていたということ。 (ちなみに最初の高級言語であるFORTLANができたのが'57年で、Lispは「2番目に古い高級言語」だったりする。) *1
ここでLispの歴史について少し。'57年に最初の版ができて以来たくさんの方言が作られたが、 現在はCommon LispとSchemeという2つのLispがよく使われている。 違いは、Common Lispがそれまでの方言の スーパーセットを目指したのに対し、Schemeはできるかぎりシンプル(かつ、強力)な仕様を目指したところ。 *2
LISP系言語はSchemeとCommon Lispを二大潮流とするが、提案された機能を原則全て導入するCommon Lispに対して、メンバーの全員一致を原則とするSchemeという特徴を持っている。
[wikipedia:Schemeより引用]
さて、もう一つは、「マクロ」と呼ばれる強力な機能を備えていること。マクロというとC言語の「#define ...」を想像するかも知れないけど、Lispのマクロはそれよりもずっと強力。 例えば、Haskellでは [ x*x | x in [1,2,3] ] と書くと [1,4,9] というリストが得られる(リスト内包表現)んだけど、Lispでは同じような機能をマクロで書くことができる。
(list-of (* x x) (x in '(1 2 3 4 5))) => (1 4 9 16 25)
このlist-ofは、関数ではない。関数だとすると実行するまえに引数が全て評価されるはずだけど、「(* x x) を計算した結果」がlist-ofに渡っても仕方がないよね。「(* x x) というコードそのもの」がlist-ofに渡らないといけない。この「コードそのもの」を扱える点が、マクロと関数の大きな違い。
さて、このように強力なマクロだが、なぜ他の言語ではあまり採用されていないのか? その理由の一つに、マクロがLispの「データとコードを同じ形(S式)で扱う」という特徴に拠っていることが挙げられる。 「コードをそのものを渡したい」と思ったとき、他の言語ではどうすれば良いだろうか?文字列?うーん。 Lispでは、コードはS式(リスト)で書かれるから、シンボルのリストを渡せばよい。
list-ofは
(define-syntax list-of (syntax-rules () ((list-of expr ...) (以下略)
のように実装される。exprにlist-of以下のコードが(リスト形式で)渡されるわけだ。 *3
つづく(かも?)