Him*_*rzi 1 lisp evaluation scheme functional-programming sicp
我正在尝试编写一个转换let形式表达式的函数:
Run Code Online (Sandbox Code Playgroud)(let ((var1 exp1) ... (varn expn)) body)
转换lambda为以下形式的(等效)表达式:
((lambda (var1 ... varn) body) exp1 ... expn)
我发现该问题的大多数解决方案似乎都是错误的,有人可以确认是这种情况吗?
;; let expression
(define (let-vars expr) (map car (cadr expr)))
(define (let-inits expr) (map cadr (cadr expr)))
(define (let-body expr) (cddr expr))
(define (let->combination expr)
(cons (make-lambda (let-vars expr) (let-body expr))
(let-inits expr)))
Run Code Online (Sandbox Code Playgroud)
我相信let->combination会返回这种形式的清单:
((lambda (var1 ... varn) body) (exp1 ... expn))
Run Code Online (Sandbox Code Playgroud)
但是,我认为它应该返回的是以下形式的列表:
((lambda (var1 ... varn) body) exp1 ... expn)
以某种方式,不应在中使用对apply函数的调用let->combination吗?应该如何let->combination修改以包含apply?
我相信 let-combination将返回这种形式的列表:
Run Code Online (Sandbox Code Playgroud)((lambda (var1 ... varn) body) (exp1 ... expn))
但是,我认为它应该返回的是以下形式的列表:
Run Code Online (Sandbox Code Playgroud)((lambda (var1 ... varn) body) exp1 ... expn)
有好消息,有坏消息。坏消息是你的信念是错误的。好消息是您的想法是正确的。也就是说,您确实需要结果((lambda …) …),这就是这段代码产生的结果。
此Scheme代码不需要任何特殊的解释器或任何内容,因此您可以进行测试,而不会遇到任何实际问题。让我们再来看一下定义:
(define (let-vars expr) (map car (cadr expr)))
(define (let-inits expr) (map cadr (cadr expr)))
(define (let-body expr) (cddr expr))
(define (let->combination expr)
(cons (make-lambda (let-vars expr) (let-body expr))
(let-inits expr)))
Run Code Online (Sandbox Code Playgroud)
那么(let->combination '(let ((x 34)) (list x))),例如,会发生什么?您将评估:
(cons (make-lambda (let-vars expr) (let-body expr))
(let-inits expr))
Run Code Online (Sandbox Code Playgroud)
这些零件会产生什么? (make-lambda …)创建您期望的lambda表达式:
(lambda (x) (list x))
Run Code Online (Sandbox Code Playgroud)
并(let-inits …)返回:
(34)
Run Code Online (Sandbox Code Playgroud)
现在的问题是,(cons '(lambda (x) (list x))'(34))'是什么?您可以轻松地进行测试;它的:
((lambda (x) (list x)) 34)
Run Code Online (Sandbox Code Playgroud)
这可能是对工作方式有些困惑的结果cons。列表可以是:空列表,'()或由cons生成的一对,其car是列表的元素,而cdr是列表的其余部分。从而:
(cons 1 '()) ;=> (1)
(cons 1 '(2)) ;=> (1 2)
(cons '(lambda (x) x) '(34)) ;=> ((lambda (x) x) 34)
Run Code Online (Sandbox Code Playgroud)
我相信let-combination将返回这种形式的列表:
Run Code Online (Sandbox Code Playgroud)((lambda (var1 ... varn) body) (exp1 ... expn))…以某种方式,在let组合中不应该使用对apply函数的调用吗?应该如何修改let-combination以使其适用?
如我们所见,代码实际上产生了您想要的结果。如果它确实产生了类似的东西((lambda (var1 ... varn) body) (exp1 ... expn)),那么您可能需要使用apply。最简单的方法是生产
(apply (lambda (var1 ... varn) body) (list exp1 ... expn))
Run Code Online (Sandbox Code Playgroud)
请注意,我们已添加apply以及对的调用list。这将需要更改的定义let->combination。一种可能性是:
(define (let->combination expr)
(cons 'apply
(cons (make-lambda (let-vars expr) (let-body expr))
(cons (cons 'list (let-inits expr))
'()))))
Run Code Online (Sandbox Code Playgroud)
另一个(简单)的选项是:
(define (let->combination expr)
(list 'apply
(make-lambda (let-vars expr) (let-body expr))
(cons 'list (let-inits expr))))
Run Code Online (Sandbox Code Playgroud)