(car (cons x y)) の評価

(define (cons x y)
  (lambda (m) (m x y)))

(define (car z)
  (z (lambda (p q) p)))

このように定義されたとき (car (cons x y)) の値がどうなるか。

単純に置き換えていけば良い。(substitute;置換)

  (car (cons x y))
= <car を定義で置き換え>
  ((cons x y) (lambda (p q) p))
= <cons を定義で置き換え>
  ((lambda (m) (m x y)) (lambda (p q) p))
= <cons の定義であるλ式を引数のλ式に適用;つまり引数 m の置き換え>
  ((lambda (p q) p) x y)
= <残るλ式を引数 x y に適用>
  x

ここでは ((lambda (m) (m x y)) (lambda (p q) p)) の評価(あるいは置換)が一番の難所だろう。

LISP(や Scheme)の世界では関数を呼び出す(適用する)ことを「(関数 引数1 引数2 引数3 ...)」のように(全体を丸括弧でくくって)表現する。
(lambda (m) (m x y)) は、 JavaScript で言えば

function(m) { return m(x, y); }

のことだ。(アロー表記でよければ m => m(x, y) )
(lambda (p q) p) は

function(p, q) { return p; }

ということ。
つまり「((lambda (m) (m x y)) (lambda (p q) p))」は

(function(m) { return m(x, y); })(function(p, q) { return p; })

ということ。 function(m) ... の関数に、関数 function(p, q) ... を渡している。だから、

(function(p, q) { return p; })(x, y)

となって、引数 p には x、 q には y をそれぞれ与えて関数を呼び出す。関数本体は p を返すと言っているので、 p に束縛された値 x が式全体を評価した結果の値になる。

この記事が気に入ったらサポートをしてみませんか?