这对我来说纯粹是一个好奇的问题:
因此,为了好玩,人们可以轻松地重新定义缺点,汽车和cdr:
(define cons+
(lambda (a b)
(lambda (f)
(f a b)
)))
(define car+
(lambda (f)
(f (lambda (a b) a))))
(define cdr+
(lambda (f)
(f (lambda (a b) b))))
这使用闭包创建列表的基本功能。在这种情况下,定义空列表的最佳方法是什么?
答案 0 :(得分:4)
您需要作为空列表的特定特殊值;你只需要一些东西,然后把它当作空列表。在Common Lisp中,列表是缺点或符号NIL。您可以采用相同的方法并使用符号NIL,或者您可以使用其他一些值,只要您始终如一地对待它。 Lisp系列中链接列表的一部分美(有时是丑陋)是内涵数据结构。它们是由一些结构和许多惯例构建的。这就是为什么我们可以使用cons单元来实现单链表,树等等。
现在,一贯对待它意味着什么?其中一些将取决于您希望它的行为方式。在Common Lisp中,您可以使用空列表调用 car 和 cdr ,然后您将返回空列表。在Scheme中,您将收到错误消息。在基于闭包的方法中,你有一个“漏洞”的抽象概念,你可以使用产生的值来调用 car + 和 cdr + 缺点+ ,你可能得到一个值。
在Lisp样式(conses和空列表)中实现单链表时,通常需要一个可以让您检查的界面:
(cons? (cons ...)) == true
(empty? empty) == true
(就这些而言,您可以实施列表?)
(define (list? x)
(or (cons? x)
(null? x)))
在您已经完成的工作之后,实现缺点功能应该不难。但是空?呢?你实际上在这里有很多自由。您可以实现空?,这样实际上有多个对象可用作空列表。只要合同有效,就可以了。
目前,您已经完成了有序对的工作实现,但它是leaky abstraction,因为某些未使用缺点创建的内容仍然可以传递给< strong> car 和 cdr 没有任何错误。你对公理很满意
(car (cons x y)) == x
(cdr (cons x y)) == y
但不是影响
(car z) == x
⇒z == (cons x _)
(cdr z) == y
⇒z == (cons _ y)
如果您能找到一种方法来实现这些含义,那么汽车和 cdr 仅适用于缺点生成的内容,则您可以弄清楚如何实现缺点?,并且可以使用相同的技术生成唯一的空列表对象。