3

我目前正在阅读《小阴谋家》的第 4 版。一个早期的练习是创建一个函数,该函数insertR在列表中给定值的右侧插入一个值。本书最终得出以下定义:

(define insertR
  (lambda (new old lat)
    (cond
      ((null? lat) (quote ()))
      (else (cond
              ((eq? (car lat) old)
               (cons old
                     (cons new (cdr lat))))
              (else (cons (car lat)
                          (insertR new old
                                   (cdr lat)))))))))

我自己的定义是这样的:

(define insertR
  (lambda (new old lat)
    (cond
      ((null? lat) (quote ()))
      ((eq? (car lat) old) (cons old (cons new (cdr lat))))
      (else (cons (car lat) (insertR new old (cdr lat)))))))

它们是等价的吗?

4

4 回答 4

3

当然这两个定义是等价的,但是你的定义更容易阅读。请记住,您只是在本书的第 3 章,作者喜欢慢慢来。在同一章的后面,在第 41 页,他们将准确地教给你你正在做的那种简化——在一个单一cond的表单中处理所有互斥的条件,而不是嵌套cond表单。

于 2012-09-23T18:19:25.613 回答
3

是的,这两个定义具有相同的行为。

这本书有两个conds 的原因是因为它们服务于两个不同的目的。外部cond区分列表数据类型的两种情况(列表是或者nullcons第二个参数是列表)。外部cond由所使用的数据类型决定;列表上的所有结构递归函数都将具有该 external cond。内部cond特定于正在定义的特定功能。

因此,虽然将它们组合起来更紧凑,但通过将它们分开,您可以使函数的结构更清楚地对应于递归类型的结构。如果您始终如一地使用该习惯用法,它会使您的结构递归函数更易于阅读、调试和维护。

于 2012-09-24T02:22:06.933 回答
3

我要和 Ryan 说同样的话:可读性仅次于正确性。事实上,如果你是学生,可读性可能比正确性更重要。

书中出现的版本的优点是它有一个双臂条件,其中一个测试空虚。这是解决问题的完全正常和预期的方法。当我看到这个拆分时,我可以迅速理解这两个代码块的作用。在您的代码中,我必须停下来花时间确保这三种情况是详尽无遗且互斥的,然后推断哪些输入属于哪些垃圾箱。

Here's what I want you to picture: it's 11:52 PM, I'm tired, my eyes hurt, and I'm reading over forty-five solutions to the same problem, written by students. I'm looking for CLARITY, darn it. If you can write your solution in a way that makes it OBVIOUS that you did it right, I'm going to give you 100% and bless your name.

于 2012-09-24T06:54:02.617 回答
2

它们是,是的,虽然我发现你的更容易阅读。cond支持多个子句,并评估每个子句,直到其中一个评估为一个true值。因此,以下内容:

(else (cond
        ((eq? (car lat) old) (cons old (cons new (cdr lat))))
        (else (cons (car lat) (insertR new old (cdr lat)))))))))

相当于将第二个的第一个子句cond移到第一个:

(cond
  ((null? lat) (quote ()))
  ((eq? (car lat) old) (cons old (cons new (cdr lat))))
  (else (cons (car lat) (insertR new old (cdr lat)))))))

也许这本书的作者认为将终止条件与其他两个分开更清楚null,但如果是这样的话,if那么就足够了,而不是cond.

于 2012-09-23T17:39:51.417 回答