6
(define ..
  (lambda (start stop)
    (cond ((> (add1 start) stop) (quote ()))
          ((eq? (add1 start) stop) (sub1 stop))
          (else (cons start (.. (add1 start) stop))))))

我已经定义了一个简单的范围函数。目的是为了

(.. 1 5)  -->  (1 2 3 4)

相反,一个奇怪的时期被添加到我的元组中,我不知道为什么:

(.. 1 5)  -->  (1 2 3 . 4)

我不明白为什么会这样。任何帮助表示赞赏

4

3 回答 3

16

Scheme 中的列表要么是空列表(在某些 Lisps 中()也称为),要么是一个 cons 单元格,其(也称为)是列表的一个元素,其(也称为)是列表的其余部分(即,另一个列表),或终止列表的原子。常规的终止符是空列表;被终止的列表被称为“正确的列表”。由任何其他原子终止的列表称为“不适当的列表”。该列表包含元素 1、2、3、4 和 5,并以 . 结尾。您可以通过以下方式构建它nilcarfirstcdrrest()()(1 2 3 4 5)()

(cons 1 (cons 2 (cons 3 (cons 4 (cons 5 ())))))

现在,当系统打印一个 cons 单元格时,一般情况是通过

(car . cdr)

例如,结果(cons 1 2)打印为

(1 . 2)

由于列表是由 cons 单元格构建的,因此您也可以将这种表示法用于列表:

'(1 2 3 4 5) ==
'(1 . (2 . (3 . (4 . (5 . ())))))

不过,这相当笨拙,所以大多数 lisps(据我所知)都有一个打印 cons 单元格的特殊情况:如果cdr是一个列表(另一个 cons 单元格或()),那么不要打印.,也不要打印周围的括号cdr(否则它会有,因为它是一个列表)。所以,如果你看到这样的结果

(1 2 3 . 4)

这意味着您有一个由 atom 终止的不正确列表4。它具有结构

(1 . (2 . (3 . 4)))

现在的问题是:在您的代码中,列表构造哪里出错了?..总是应该返回一个正确的列表,所以让我们看一下案例:第一个案例总是返回一个正确的列表(空列表):

((> (add1 start) stop) (quote ()))

第二种情况看起来它可以返回不是列表的东西(假设(sub1 stop) == (- stop 1)):

((eq? (add1 start) stop) (sub1 stop))

现在,如果..运行正常,那么第三种情况将始终返回一个正确的列表(因为(cons x y)如果y是正确的列表):

(else (cons start (.. (add1 start) stop)))

让你的第二个案例返回一个列表,你应该已经准备好了。

于 2013-05-04T23:03:58.573 回答
2

你的表情(sub1 stop)需要阅读(list (sub1 stop))

为了cons建立一个合适的列表,第二个元素需要是一个列表本身。因此,您的函数应该为每个子句..返回某种类型的列表。cond

于 2013-05-04T23:14:10.690 回答
1

删除这部分条件

 ((eq? (add1 start) stop) (sub1 stop))

它导致过早完成。

于 2013-05-05T11:22:27.077 回答