6

我没有在 Common-Lisp 中得到这第一件事/最后一件事。是的,我知道它是如何工作的,但我不明白为什么它会这样工作。

基本上,要获得列表中的第一项,我可以使用(first mylist). 但是,如果我想要最后一项,(last mylist)不要给我;相反,它给了我一个列表,其中包含我列表中的最后一项!

(我正在使用 Clozure-CL,它还有一些其他奇怪的东西,对我来说似乎是错误,但是,因为我是 Lisp-n00b,所以我尽量不要陷入旧的“解释器坏了!”把戏:) )

因此,例如:

? (setq x '((1 2) (a b)))
=> ((1 2) (A B))

? (first x)
=> (1 2)  ; as expected

? (last x)
=> ((A B))  ; why a list with my answer in it?!

? (first (last x))
=> '(A B)  ; This is the answer I'd expect from plain-old (last x)

有人可以帮我理解为什么最后会这样做吗?我是否错误地使用了这些物品?真的first是奇球吗?!

谢谢!

4

4 回答 4

8

在 Common Lisp中,应该从文档last中返回一个列表:

last list &optional n => tail
list---a list, which might be a dotted list but must not be a circular list.
n---a non-negative integer. The default is 1.
tail---an object. 

last 返回列表的最后 n 个 conses(不是最后 n 个元素)。如果 list 是 (),last 返回 ()。

例如:

(setq x (list 'a 'b 'c 'd))
(last x) =>  (d)

是的,这是违反直觉的。在其他风格的 Lisp 中,它的工作原理顾名思义,例如在 Racket(一种 Scheme 方言)中:

(define x '((1 2) (a b)))
(first x) => '(1 2)
(last x) => '(a b)

(define x (list 'a 'b 'c 'd))
(last x) =>  'd
于 2013-07-18T19:14:12.527 回答
7

返回最后一个元素除了访问最后一个元素外并没有多大用处;返回最后一个缺点可以让你做这样的事情:

(let ((x (list 1 2 3)))
  (setf (cdr (last x)) '(4))
  x)

=> '(1 2 3 4)

虽然您仍然可以将最后一个元素作为(car (last x)).

于 2013-07-18T19:58:28.880 回答
4

Common Lisp 命名错误的函数last给了你最后的缺点

它可能应该被称为tail,因为有一个 function tailp,但我猜这个名字是出于历史/兼容性的原因。

通常,它会为您提供列表的第 n 个尾部,或列表末尾之前的第 n 个缺点。

于 2013-07-18T19:17:45.867 回答
4

这就是它的方式。first并且last不是一对互补的操作。与和last更密切相关。还有一个构造了一个新列表,它省略了给定列表中的最后一项。restnthcdrbutlast

firstvslast与 how 相比什么都不是,与getandgetf无关。setsetf

于 2013-07-18T19:47:38.277 回答