如何确定列表是否为列表

时间:2013-01-17 01:39:03

标签: common-lisp

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

我的第一次尝试:

(defun alistp (list)
    (and (listp list)
         (every (lambda (c)
                    (and (consp c)
                         (or (atom (cdr c))
                             (null (cddr c))))))
                list)))

返回(alistp '((1 . 2) (2 . 3)))

的T.

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

的NIL

有解决方案吗?

1 个答案:

答案 0 :(得分:5)

好吧,让我们看一下definition关联列表:

  

协会名单代表一个关联的一个conses列表   带有值的键,每个缺点的汽车是键,而cdr是   与该键相关联的值。

鉴于此,这将是alistp

的可能实现
(defun alistp (alist)
  (and (listp alist)           ; a list
       (every #'consp alist))) ; of conses

现在,从你的代码示例中我可以看出你可能已经能够自己实现这个,但是你似乎对alist有不同的定义。我假设你看到的alists的例子看起来或多或少都像这样:((a . x) (b . y)),也许是((a . x) (b . (y z)))但是列表作为最后一个元素的虚线列表只是 - 一个列表,并且来自你的示例输入很明显,您希望允许列表作为值。 (无论如何,你为什么不呢?)

我想,您必须意识到,您的示例输入((1 . (4 5 6))) ((1 4 5 6))完全相同,这就是我主要看到列表为alist的方式他们在代码中使用的值 - 至少,这是我通常写它们的方式。

现在,您似乎也希望排除nil值,尽管它们也是列表 - 只是空的()。所以,你实际想到的定义是这样的:

  

协会名单表示关联的cons单元列表   具有非零值的键,其中每个缺点的汽车是键,而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

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