如何确定列表是否为列表

Ada*_*ite 2 common-lisp

有没有一种简单的方法来确定列表是否实际上是一个列表?

我的第一次尝试:

(defun alistp (list)
    (and (listp list)
         (every (lambda (c)
                    (and (consp c)
                         (or (atom (cdr c))
                             (null (cddr c))))))
                list)))
Run Code Online (Sandbox Code Playgroud)

返回T表示 (alistp '((1 . 2) (2 . 3)))

但是NIL for (alistp '((1 . (4 5 6))))

有解决方案吗?

dan*_*lei 5

那么,让我们看一下关联列表的定义:

协会名单 表示键与值的关联的conses列表,其中每个cons的汽车是键,cdr是与该键相关联的值.

鉴于此,这将是一个可能的实现alistp:

(defun alistp (alist)
  (and (listp alist)           ; a list
       (every #'consp alist))) ; of conses
Run Code Online (Sandbox Code Playgroud)

现在,从你的代码示例中我可以看出你可能已经能够自己实现这个,但是你似乎对alist有不同的定义.我假设你看到的alists的例子看起来或多或少都是这样的:((a . x) (b . y))也许((a . x) (b . (y z)))但是列表作为最后一个元素的虚线列表只是 - 一个列表,从你的示例输入中可以清楚地看到你想允许列表作为价值观.(不管怎么说,你为什么不呢?)

你必须认识到,我想,是你的榜样输入((1 . (4 5 6)))完全一样((1 4 5 6)),这是多么我主要是看到名单alists在代码中使用它们的值-至少,这是多么我平时写他们.

现在,你似乎也想要排除nil值,虽然它们也是列表 - 只是空的().所以,你实际想到的定义是这样的:

协会名单 表示密钥与非零值的关联的缺点单元列表,其中每个缺点的汽车是密钥,而cdr是与该密钥相关联的值.

如果这真的是你想要的,请遵循新的定义:

(defun alistp (alist)
  (flet ((true-cdr-p (element)
           (and (consp element)        ; cons cell
                (cdr element))))       ; with non-nil cdr (i.e. value) 
    (and (listp alist)                 ; a list
         (every #'true-cdr-p alist)))) ; of cons cells with non-nil cdr
Run Code Online (Sandbox Code Playgroud)

或类似的东西.不过我建议坚持使用上面的简单版本.