【问题标题】:Why closure use seems so "chicken or egg"为什么封闭使用看起来如此“鸡或蛋”
【发布时间】:2014-10-22 16:53:53
【问题描述】:

我已经阅读并有点理解Use of lambda for cons/car/cdr definition in SICP。我的问题是理解它背后的原因。我的第一个问题是盯着看

(define (cons x y)
 (lambda (m) (m x y)))

并且不理解这个函数实际上是如何进行任何形式的consing的。我从各种 Lisp/Scheme 书籍中了解到,Consing 是将内容放入列表中,即,

(cons 1 ()) => (1)

怎么样

(define (cons x y)
 (lambda (m) (m x y)))

做任何事情比如consing?但随着我脑海中的光亮:cons 只是 car 和 cdr 最终定义的占位符。所以汽车是

 (define (car z)
   (z (lambda (p q) p)))

它预期传入的 z。但是这个z是什么?当我看到这个用法时:

 (car (cons 1 2))

我终于明白了,是的,整个 cons 函数是 z,也就是说,我们将 cons 传递给 car!多么奇怪!

((lambda (m) (m 1 2)) (lambda (p q) p)) ; and then
((lambda (p q) p) 1 2)

这导致抓取第一个表达式,因为基本的汽车操作可以被认为是一个布尔值为真的 if 语句,因此,抓取第一个。

是的,所有列表都可以被认为是 cons-ed together 表达式,但是我们通过这个奇怪的向后定义赢得了什么?就好像任何最初的、独立的 cons 定义都没有密切关系。就好像 something 的使用定义了 something,就好像没有 something 直到它的使用限制它。这是闭包的主要用途吗?谁能给我一些其他的例子?

【问题讨论】:

  • 我不认为我们能比Oscar's answer 做得更好。而且,您应该尝试 REPL 中的不同步骤来亲自查看。
  • 我了解奥斯卡。我不明白为什么,我们为什么要这样做?这种闭包有什么用途?其他例子。等等等等
  • 我也花了一段时间才明白这一点。我认为这个 cons/car/cdr 定义是用来说明数据结构和算法可以从任何特定的内部表示方式中抽象出来。另一个例子是,使用零和 succ 和 pred 函数的适当定义,您可以“构造”所有基本自然数数学(加法、减法、乘法、比较等),而无需使用语言固有的 +、-、* 运算符。它可能效率低下,但它从任何内部二进制表示中抽象出数字。
  • (1)(1 . ()) 代表您在评估 (cons 1 '()) 时得到的结果,但它不是存储在内存中的实际对象。就像2040 是十进制数32 的正常表示,只是在不同的基础上。如果您要实现自己的 Scheme 实现,您将如何实现 cons 将决定如何实现 carcdr 以及您需要如何实现 readdisplay

标签: scheme lambda-calculus


【解决方案1】:

但是我们通过这个奇怪的落后定义赢得了什么?

练习的重点是证明数据结构可以完全按照函数来定义;数据结构作为语言中的原始构造不是必需的——如果你有函数(即闭包),这就足够了。这显示了函数的威力,并且对于函数式编程之外的人来说可能是令人难以置信的。

在一个真正的项目中,我们实际上不会以这种方式定义数据结构。使用语言提供的数据结构构造会更有效。但重要的是要知道我们可以这样做。在计算机科学中,能够将一个构造(数据结构)“简化”为另一个构造(函数)是很有用的,这样如果我们证明第二个构造的某些内容,它也适用于第一个构造。

【讨论】:

    猜你喜欢
    • 2011-05-09
    • 2011-02-17
    • 2011-01-12
    • 2010-10-29
    • 1970-01-01
    • 2013-10-20
    • 1970-01-01
    • 2017-03-08
    • 2016-01-01
    相关资源
    最近更新 更多