(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 が式全体を評価した結果の値になる。
この記事が気に入ったらサポートをしてみませんか?