Lisp中的递归范围增加了一个时期?

时间:2013-05-04 22:46:00

标签: lisp scheme

(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)

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

3 个答案:

答案 0 :(得分:15)

Scheme中的列表是空列表()(在某些Lisp中也称为nil),或者是car(也称为first的缺点列表)是列表的一个元素,其cdr(也称为rest)是列表的其余部分(即另一个列表),或者是终止列表的原子。传统的终结符是空列表();被()终止的列表被称为“正确列表”。被任何其他原子终止的列表称为“不正确的列表”。列表(1 2 3 4 5)包含元素1,2,3,4和5,并由()终止。您可以通过

构建它
(cons 1 (cons 2 (cons 3 (cons 4 (cons 5 ())))))

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

打印它
(car . cdr)

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

(1 . 2)

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

'(1 2 3 4 5) ==
'(1 . (2 . (3 . (4 . (5 . ())))))
但是,这是相当笨重的,所以大多数lisps(我所知道的)都有一个打印cons单元格的特殊情况:如果cdr是一个列表(另一个cons单元格,或() ),然后不打印.,并且不打印cdr的周围括号(否则它将具有,因为它是一个列表)。所以,如果你看到像

这样的结果
(1 2 3 . 4)

这意味着你有一个由原子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))) 是正确的列表):

{{1}}

让你的第二个案例返回一个列表,你应该全部设置。

答案 1 :(得分:1)

您的表达式(sub1 stop)需要阅读(list (sub1 stop))

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

答案 2 :(得分:1)

删除cond的这部分

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

这导致过早完成。