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

vim*_*vim 5 lisp scheme

(define ..
  (lambda (start stop)
    (cond ((> (add1 start) stop) (quote ()))
          ((eq? (add1 start) stop) (sub1 stop))
          (else (cons start (.. (add1 start) stop))))))
Run Code Online (Sandbox Code Playgroud)

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

(.. 1 5)  -->  (1 2 3 4)
Run Code Online (Sandbox Code Playgroud)

相反,我的元组中添加了一个奇怪的时期,我不明白为什么:

(.. 1 5)  -->  (1 2 3 . 4)
Run Code Online (Sandbox Code Playgroud)

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

Jos*_*lor 15

方案A列表要么是空列表()(也称为nil在一些的Lisp)或cons单元,其car(也称为first)是与所述列表的一个元件,其cdr(也称为rest)或者是列表的其余部分(即,另一个列表),或终止列表的原子.传统的终结符是空列表(); 被终止的名单()被称为"适当的名单".被任何其他原子终止的列表称为"不正确的列表".该列表(1 2 3 4 5)包含元素1,2,3,4和5,并以().你可以通过构建它

(cons 1 (cons 2 (cons 3 (cons 4 (cons 5 ())))))
Run Code Online (Sandbox Code Playgroud)

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

(car . cdr)
Run Code Online (Sandbox Code Playgroud)

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

(1 . 2)
Run Code Online (Sandbox Code Playgroud)

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

'(1 2 3 4 5) ==
'(1 . (2 . (3 . (4 . (5 . ())))))
Run Code Online (Sandbox Code Playgroud)

但是,这是相当笨重的,所以大多数lisps(我所知道的)都有一个打印cons单元格的特殊情况:如果cdr是一个列表(或者是另一个cons单元格,或者()),那么就不要打印.,而不是打印周围的括号cdr(否则它将具有,因为它是一个列表).所以,如果你看到像这样的结果

(1 2 3 . 4)
Run Code Online (Sandbox Code Playgroud)

这意味着你有一个由原子终止的不正确的列表4.它有结构

(1 . (2 . (3 . 4)))
Run Code Online (Sandbox Code Playgroud)

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

((> (add1 start) stop) (quote ()))
Run Code Online (Sandbox Code Playgroud)

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

((eq? (add1 start) stop) (sub1 stop))
Run Code Online (Sandbox Code Playgroud)

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

(else (cons start (.. (add1 start) stop)))
Run Code Online (Sandbox Code Playgroud)

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