当你这样做时:
(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)求值变为和变为。的评估发生在您申请时,因此如果您调用它将返回与在创建闭包的环境中评估相同的结果。由于您将主机与客人混合在一起,因此您将无法处理自由变量,因此无法开始工作。cadr1x2(caddr e)((lambda (cadr x)(caddr e)) 'ignored1 'ignored2)(caddr e)(eval `(lambda ,(cadr x) ,(caddr e)))
由于您正在制作解释器,因此您的用户定义过程将是数据结构,您apply将知道如何处理它。表单的评估应该返回可以识别为闭包的东西,并且您不能在解释器中执行任何其他代码来欺骗它,引用它被评估的地方的词法范围以及cdrif 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。您所做的大多数设计选择既有优点也有缺点,而且玩起来很有趣。