首页 > 解决方案 > 理解 Common Lisp 中的函数 `tailp`

问题描述

在浏览 Bert Burgemeister 的“Common Lisp Quick Reference”时,我绊倒了tailp

首先,我误解了这个函数的定义。我试过了:

(tailp '(3 4 5) '(1 2 3 4 5))

但它回来了

NIL

CLTL2说,如果第一个参数是任何现有的,tailp则为真。(nthcdr n list)n

(nthcdr 2 '(1 2 3 4 5))
;; (3 4 5)

我进一步尝试:

(tailp '(3 4 5) '(1 2 3 4 5))
;; NIL - and I would expect: T following the definition above.

(tailp '() '(1 2 3 4 5))
;; T
(tailp '5  '(1 2 3 4 . 5))
;; T

直到我尝试过(然后明白tailp寻找哪个共享甚至相同的地址)cdrl

(defparameter l '(1 2 3 4 5 6))
(tailp (nthcdr 3 l) l)
;; T

但后来我有我的下一个问题:

For what such a function is useful at all?

会不会是一个更有用的函数来查看子列表是否是列表的一部分?(或者看起来像列表的一部分,而不是必须共享相同的地址?)

评论:

啊,好吧,我慢慢开始明白了,也许这有点像列表eqcdr一部分……有点……“第一个参数cdr的给定列表eq的任何导数?”。

但也许有人可以向我解释这种测试在哪些情况下非常有用?

评论:

在与@Lassi的长时间讨论中,我们发现:

切勿tailp在循环列表中使用!

因为行为是未定义的(已经在 SBCL 中有问题)。tailp用于非循环列表也是如此。

标签: lispcommon-lispsbclclisp

解决方案


的基本目的tailp是检查是否有共享的列表结构。这意味着cons 单元格是否相同(这意味着EQL作为谓词) - 而不仅仅是 cons 单元格的内容。

还可以检查一个项目是否在最后一个cdr

CL-USER 87 > (tailp t '(1 2 3 4 . t))
T

CL-USER 88 > (tailp nil '(1 2 3 4 . nil))
T

CL-USER 89 > (tailp nil '(1 2 3 4))
T

CL-USER 90 > (tailp #1="e" '(1 2 3 4 . #1#))
T

这是 Common Lisp 中很少使用的函数之一。


推荐阅读