你的程序相当于
(let ((f (lambda (g) (lambda (x) (g (+ (g x) (g x)))))))
(let ((e (lambda (x) (* x 3))))
(let ((d (f e)))
(d 4))))
一般来说,应该使用letrec,而不是let,但在这里没有区别。 letrec 允许过程在其主体内引用自己的名称,即递归。 let 不允许此类引用。例如,定义 f 的 lambda 表达式不包含对 f 的任何引用。
现在,评估继续尝试找出d 的值,将其用作要以4 的值作为参数调用的函数。因此执行应用程序(f e)。一般来说,一个应用程序((lambda (x) ...) v)被简化为(let ((x v)) ...):
(let ((f (lambda (g) (lambda (x) (g (+ (g x) (g x)))))))
(let ((e (lambda (x) (* x 3))))
(let ((d (let ((g e)) ; <---
(lambda (x) (g (+ (g x) (g x)))) )
))
(d 4))))
返回一个闭包:
(let ((f (lambda (g) (lambda (x) (g (+ (g x) (g x)))))))
(let ((e (lambda (x) (* x 3))))
(let ((g e))
(let ((d (lambda (x) (g (+ (g x) (g x))))))
(d 4))))) ; <---
现在发现d的值是一个过程,所以执行(d 4)的应用:
(let ((f (lambda (g) (lambda (x) (g (+ (g x) (g x)))))))
(let ((e (lambda (x) (* x 3))))
(let ((g e))
(let ((d (lambda (x) (g (+ (g x) (g x))))))
(let ((x 4))
(g (+ (g x) (g x))) ))))) ; <---
(let ((f (lambda (g) (lambda (x) (g (+ (g x) (g x)))))))
(let ((e (lambda (x) (* x 3))))
(let ((g e))
(let ((d (lambda (x) (g (+ (g x) (g x))))))
(let ((x 4))
(let ((temp1 (+ (g x) (g x)))) ; <---
(g temp1) ))))))
这是
......
(let ((x 4))
(let ((temp2 (g x)) ; <---
(temp3 (g x)))
(let ((temp1 (+ temp2 temp3)))
(g temp1) )))))))
......
(let ((x 4))
(let ((temp2 ( (lambda (x1) (* x1 3)) x )) ; <---
(temp3 (g x)))
(let ((temp1 (+ temp2 temp3)))
(g temp1) )))))))
......
(let ((x 4))
(let ((temp2 (let (x1 x) (* x1 3))) ; <---
(temp3 (g x)))
(let ((temp1 (+ temp2 temp3)))
(g temp1) )))))))
......
(let ((x 4))
(let ((temp2 (let (x1 4) (* x1 3))) ; <---
(temp3 (g x)))
(let ((temp1 (+ temp2 temp3)))
(g temp1) )))))))
......
(let ((x 4))
(let ((temp2 (* 4 3)) ; <---
(temp3 (g x)))
(let ((temp1 (+ temp2 temp3)))
(g temp1) )))))))
等等。这不是 Scheme 实际操作的方式,而是关闭方式。终于到了
......
(let ((x 4))
(let ((temp2 12)
(temp3 12))
(let ((temp1 24))
(g temp1) ))))))) ; <---
......
(let ((temp1 24))
( (lambda (x2) (* x2 3)) temp1) ))))) ; <---
......
(let (x2 24) (* x2 3)) )))) ; <---
......
(* 24 3) )))) ; <---
......
72 )))) ; []