我正在阅读“Little Schemer”一书,并完成各种功能。一般来说,我最终会得到与书籍相同的版本,但不能用于eqlist ?,这是一个测试两个列表相等的函数。
我已经尝试过对我的版本进行测试,它会传递给我的任何东西。然而它与“Little Schemer”版本略有不同,我希望有人对我是否遗漏某些东西持有意见 - 我怀疑是这样的。
我的版本:
(define eqlist?
(lambda (list1 list2)
(cond
((and (null? list1)(null? list2))#t)
((or (null? list1)(null? list2))#f)
((and (atom? list1)(atom? list2))(eqan? list1 list2))
((or (atom? list1)(atom? list2)) #f)
(else
(and(eqlist? (car list1) (car list2))
(eqlist? (cdr list1) (cdr list2)))))))
这本书的版本:
(define eqlist2? ;This is Little Schemer's version
(lambda (list1 list2)
(cond
((and (null? list1)(null? list2)) #t)
((or (null? list1)(null? list2)) #f)
((and (atom? (car list1))(atom? (car list2)))
(and (eqan? (car list1)(car list2))(eqlist2? (cdr list1)(cdr list2))))
((or (atom? (car list1))(atom? (car list2))) #f)
(else
(and (eqlist2? (car list1)(car list2))
(eqlist2? (cdr list1)(cdr list2)))))))
在这两种情况下,eqan的定义是:
(define eqan?
(lambda (a1 a2)
(cond
((and (number? a1)(number? a2)) (equal? a1 a2))
((or (number? a1)(number? a2)) #f)
(else (eq? a1 a2)))))
谢谢!
Joss Delage
答案 0 :(得分:6)
如果在原子或不正确的列表(一对不是列表 - 像(1 2 . 3)
)中作为参数传递,那么书籍版本就会破坏。 (注意它确实适用于'()
- 当然不确定TLS是否认为这是一个原子。)这使得你的函数实际上更加健壮,尽管可能更好地命名为eqv?
/ {{ 1}}比equal?
。 (我在eqlist?
中使用equal?
来测试数字相等性,但传统上这个名称附加到通用值相等测试函数。)
基本上,eqan?
适用于任何类型的参数,假设(1)eqlist?
能够告诉对(atom?
和car
的事物)非对(它是cdr
的否定版本),(2)pair?
测试原子的等式,(3)一切都是eqan?
或一对或一个原子。 (好吧,实际上'()
是我眼中的一个原子 - 而Petite Chez Scheme也同意。)书籍版本适用于正确的列表(包括'()
),做出类似的假设,并忽略了遇到一个问题的可能性。不正确的名单。
如果本书稍后会介绍一个更强大的相等测试功能,我不会感到惊讶,但我没有它可以检查。无论如何,你发布的'()
书的版本似乎是为了说明列表背后的基本思想,而不是你真正想要在日常编程中使用的东西。实际上,eqlist?
的给定版本会在一个不受限制的环境中中断,在这种环境中需要考虑更多的原子类型的数据,其中至少需要单独考虑字符串,从而使列出的假设无效。上面的第二段并打破了eqan?
的两个版本。
答案 1 :(得分:1)
这是我的版本:
(define eqlist?
(lambda (l1 l2)
(cond
((and (null? l1) (null? l2))
#t)
((and (atom? (car l1)) (atom? (car l2)))
(and (eq? (car l1) (car l2)) (eqlist? (cdr l1) (cdr l2))))
(else
(and (eqlist? (car l1) (car l2)) (eqlist? (cdr l1) (cdr l2)))))))