全5515文字
PR

 lambdaを使うともうちょっと面白いことができる。

(define (add-n n)
  (lambda (x) (+ x n)))

((add-n 3) 5)

 ここでは、add-nという関数の処理として無名関数を記述している。こうすると、add-nが返す値は「add-nに与えられたnの値を足す関数」になる。このように「返り値として関数を返す関数」を「高階関数」と呼ぶ。「引数として関数を取る関数」も高階関数だ。Schemeでは関数を値として自由に扱える。

 「((add-n 3) 5)」の意味を順番に考えてみよう。まずadd-nに3を渡すことで「与えられた引数に3を足す関数」が返ってくる。これに5を渡すことで、最終的には8という結果になる。

 いったん関数名を付けてから実行することも可能だ。こちらのほうが分かりやすいかもしれない。

(define (add-n n)
  (lambda (x) (+ x n)))

(define add-3 (add-n 3))

(add-3 5)

 Schemeならではの不思議なコードも紹介しよう。先に説明したようにSchemeでは演算子と関数にほとんど違いはなく、演算子も単なる値として扱うことができる。つまり引数として演算子を取るような関数をつくれるのだ。

(define (mycalc op)
  (lambda (x) (op x x)))

((mycalc +) 10)
((mycalc *) 10)

 mycalcは、引数として「+」を与えたときには足し算、「*」を与えたときにかけ算を行う関数を返している。実行すると「20」と「100」になるのを確認できる。

 ここまで来ると頭がついてこない読者が多いかもしれない。時間をかければ必ず理解できるので、あきらめずにコードの意味を追っていってほしい。理解できたときにはきっと別の世界が広がっているはずだ。

新しい文法を生み出せるLispの究極奥義「マクロ」

 エッセー「普通のやつらの上を行け」の中でグレアム氏は、Lispが強力な理由として真っ先に「マクロ」という機能を挙げている。Lispのマクロを使えば、言語の新しい構文を生み出せる。Lispになくてはならない機能だ。

 マクロとはどんな機能なのかを具体的に見ていこう。条件分岐を実現する「if」の再発明を題材として取り上げる。