トップ «前の日記(2006-06-14) 最新 次の日記(2006-06-25)» 編集

Route 477



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

つづく(かも?)

*1 最初のLispはFORTLANで実装されていたらしい

*2 ちなみにEmacsの拡張言語であるEmacs LispはSchemeよりはCommon Lispに似ている。でもCommon Lispとは違う。xyzzy(Windows要のEmacs風エディタ)はCommon Lispを採用している

*3 ちなみにこのマクロはLispの一方言であるSchemeのコードだが、「...」は僕が省略したわけではなく実際に「...」と書く。識別子にいろいろな記号を使えるのもLispの特徴の一つである(識別子は必ず空白で区切られるので、記号を使ってもまぎらわしくならない)。