为什么这个LISP代码会发出句号或抱怨列表不能以4结尾?

dro*_*mon 1 lisp common-lisp

我刚开始学习LISP只是为了它,所以我对它完全陌生.我确实有其他语言的经验.我试着写一个完全按原样返回列表的函数,除了没有最后一个元素.

虽然我打算重写这个函数,因为我确信有一个更简单的方法,我的版本产生了一些非常不寻常的输出.为了记录,我正在使用CLISP环境.

(defun my-butlast (L)
    (if (null (rest L))
      nil
      (if (eq nil (my-butlast (rest L)))
         (first L)
         (cons (first L) (my-butlast (rest L)))
      )
    )
)

(my-butlast '(1 2 3 4 5))
Run Code Online (Sandbox Code Playgroud)

这产生了输出 (1 2 3 . 4)

所以我的问题是,问题出在哪里?

此外,如果我试图运行,(length (my-butlast '(1 2 3 4)))我会得到一个神秘的错误:正确的列表不能以4结尾.这是什么意思?

Bar*_*mar 6

.在a表示用于conscdr不是NIL.例如

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

显示为

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

考虑一下你的功能会发生什么

(my-butlast '(1 2))
Run Code Online (Sandbox Code Playgroud)

测试(eq nil (my-butlast (rest L))将是真的,所以它返回(first L).请注意,这只是数字1,而不是包含的列表1.您需要更改为:

(if (eq nil (my-butlast (rest L)))
    (list (first L))
    (cons (first L) (my-butlast (rest L)))
)
Run Code Online (Sandbox Code Playgroud)

顺便说一下,写作更加惯用(null (my-butlast (rest L))).