lambda - 在 SICP 中使用 lambda 定义 cons/car/cdr

标签 lambda scheme racket sicp

当我在 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吗?就是这样!它所期望的功能。

理解了上面的内容,就很容易明白carcdr是如何工作的;让我们 剖析解释器如何一次一步地评估 carcdr:

; 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 。 这有多酷?我们只需要存储和检索任意数据的函数!

carcdr 的嵌套组合为 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/

相关文章:

使用 Racket 宏动态定义符号和宏

Python 2 列表理解和评估

filter - 过滤器是如何实现的?

c# - 正在使用 "out"错误做法

list - 方案 - 列表的子集

java - 在 clojure 中, (= 'a ' a) 指的是 'same atom' 吗?

racket - 打字/ Racket 中的/列表注释

数据/集合中的 Racket 序列与内置序列

c++ - 使用 lambda 和定点组合器递归访问 `std::variant`

c++ - 如何在 C++ 中创建带返回值的内联作用域?