简体   繁体   中英

How to determine if a list is an alist

Is there a simple way to determine if a list is actually an alist ?

My first attempt:

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

Returns T for (alistp '((1 . 2) (2 . 3)))

But NIL for (alistp '((1 . (4 5 6))))

Is there a solution?

Well, let's look at the definition of association lists:

association list n. a list of conses representing an association of keys with values, where the car of each cons is the key and the cdr is the value associated with that key.

Given that, this would be a possible implementation of alistp :

(defun alistp (alist)
  (and (listp alist)           ; a list
       (every #'consp alist))) ; of conses

Now, from your code example I can tell that you'd have probably been able to implement this yourself, but you seem to have a different definition of alist in mind. I assume the examples of alists you've seen all looked more or less like this: ((a . x) (b . y)) , maybe ((a . x) (b . (yz))) But a dotted list with a list as its last element is just – a list, and from your example input it's clear that you want to allow lists as values. (Why wouldn't you, anyway?)

What you have to realize, I suppose, is that your example input ((1 . (4 5 6))) is exactly the same as ((1 4 5 6)) , which is how I mostly see alists with lists as their values used in code – at least, it is how I usually write them.

Now, you also seem to want to exclude nil values, although they're lists, too – just empty ones () . So, the definition you actually have in mind is rather something like this:

association list n. a list of cons cells representing an association of keys with non-nil values, where the car of each cons is the key and the cdr is the value associated with that key.

If that is really what you want, follow the new definition:

(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

Or something like that. I suggest sticking with the simple version above, though.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM