当你这样做时:
(define x '(lambda (n) (+ n 1)))
您正在使绑定x
指向列表结构(lambda (n) (+ n 1))
。lambda
它与以下形式无关:
(define x2 (lambda (n) (+ n 1)))
你可以申请的地方,(x2 1) ; ==> 2
因为它的价值是一个闭包/过程/函数,因为 lambda 形式被评估。
(lambda (cadr x)(caddr e))
不求值(cadr x)
,而是用形式参数创建一个闭包,cadr
这样x
您就可以应用结果,使得闭包中的((lambda (cadr x) ...) 1 2)
求值变为和变为。的评估发生在您申请时,因此如果您调用它将返回与在创建闭包的环境中评估相同的结果。由于您将主机与客人混合在一起,因此您将无法处理自由变量,因此无法开始工作。cadr
1
x
2
(caddr e)
((lambda (cadr x)(caddr e)) 'ignored1 'ignored2)
(caddr e)
(eval `(lambda ,(cadr x) ,(caddr e)))
由于您正在制作解释器,因此您的用户定义过程将是数据结构,您apply
将知道如何处理它。表单的评估应该返回可以识别为闭包的东西,并且您不能在解释器中执行任何其他代码来欺骗它,引用它被评估的地方的词法范围以及cdr
if lambda的每个部分.
我的一个人这样做:
(define closure-tag (list 'closure)) ; make something that is not `eq?` with enything else
(define (closure? expr)
(and (pair? expr)
(eq? closure-tag (car expr))))
(define (lambda->closure expr env)
`(,closure-tag ,env ,@(cdr expr)))
因此,评估 lambda(lambda (n) (+ n 1))
变为((closure) ((#t . #t) ...) (n) (+ n 1))
并申请((lambda (n) (+ n 1)) 2)
将(+ n 1)
与 environment 一起评估((n . 2) (#t . #t) ...)
。结构的选择无关紧要,因为结构是 lambda 形式的评估和您的应用之间的协议。
您可以使lambda
表单成为程序,但它仍然不是来宾源的主机版本,而是某种优化。我最近的一个是eval
这样做的,并且总是接受 2 个论点。参数列表未评估和环境。用eval
行话来说,基元是用evlis
和咖喱化的apply
。您所做的大多数设计选择既有优点也有缺点,而且玩起来很有趣。