当我在 SICP 中遇到以下 cons 和 car 的“替代”定义时,我刚刚开始觉得自己对 lambda 在 Racket 和方案中的使用有一个模糊的理解
(define (cons x y)
(lambda (m) (m x y)))
(define (car z)
(z (lambda (p q) p)))
(define (cdr z)
(z (lambda (p q) q)))
我一生都无法解析它们。
任何人都可以解释如何以对新手有意义的方式解析或扩展这些内容吗?
最佳答案
这是一种有趣的表示数据的方式:作为函数。请注意,这
cons
的定义返回一个 lambda
,它封闭参数 x
和 y,捕获它们内部的值。另请注意,返回的 lambda
接收函数 m
作为参数:
;creates a closure that "remembers' 2 values
(define (cons x y) (lambda (m) (m x y)))
;recieves a cons holding 2 values, returning the 0th value
(define (car z) (z (lambda (p q) p)))
;recieves a cons holding 2 values, returning the 1st value
(define (cdr z) (z (lambda (p q) q)))
在上面的代码中,z
是一个闭包,与cons
创建的相同,并且在
我们将另一个 lambda
作为参数传递给它的过程主体,
还记得m
吗?就是这样!它所期望的功能。
理解了上面的内容,就很容易明白car
和cdr
是如何工作的;让我们
剖析解释器如何一次一步地评估 car
、cdr
:
; lets say we started with a closure `cons`, passed in to `car`
(car (cons 1 2))
; the definition of `cons` is substituted in to `(cons 1 2)` resulting in:
(car (lambda (m) (m 1 2)))
; substitute `car` with its definition
((lambda (m) (m 1 2)) (lambda (p q) p))
; replace `m` with the passed parameter
((lambda (p q) p) 1 2)
; bind 1 to `p` and 2 to `q`, return p
1
总结一下:cons
创建一个“记住”两个值的闭包,car
接收该闭包并将其传递给一个充当选择器的函数
第零个值,cdr
充当第一个值的选择器。 key
这里需要理解的是 lambda 充当
closure 。
这有多酷?我们只需要存储和检索任意数据的函数!
car
和 cdr
的嵌套组合为 defined up to 4 deep在大多数 LISP 中。示例:
(define caddr (lambda (x) (car (cdr (cdr x)))))
关于lambda - 在 SICP 中使用 lambda 定义 cons/car/cdr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21769348/