Search code examples
common-lisp

Get only the keys of a plist


I do the following code to retrieve only the keys of a plist:

(loop :for (key nil) :on config :by #'cddr
      :collect key))

Running this produces:

CONFIG-TEST> (loop :for (key nil) :on '(:foo 1 :bar 2) :by #'cddr
                   :collect key)
(:FOO :BAR)

Is there a more 'functional' way to do this than using LOOP?


Solution

  • Using the SERIES package, scan-plist returns two series, one for the keys, the other for values:

    (scan-plist '(:a 3 :b 2))
    => #Z(:A :B)
       #Z(3 2)
    

    You can rely on this to collect the first series as a list:

    (collect 'list (scan-plist '(:a 3 :b 2)))
    

    More generally, you may want to process the values in some way, so you would use mapping. For example, here is a plist-alist made with SERIES:

    (defun plist-alist (plist)
      (collect 'list
        (mapping (((k v) (scan-plist plist))) (cons k v))))