Search code examples
common-lispplistsymbols

Lisp plist only in context of symbol's property list cell?


Basically, I'm wondering if there is such a thing as a plist in Common Lisp outside the concept of the built-in symbol property list. So if I have

(setq Joe '(:fav-season  "Fall" :fav-color  "Blue"))

then I do

(setf (get 'Joe 'fav-season) "Summer")
(setf (get 'Joe 'fav-color) "Green")

I've got two separate plists associated with Joe going at once, one ad-hoc, the other "official" because it's bound to the symbol Joe.

(get 'Joe 'fav-color)
"Green"

or

(symbol-plist 'Joe)
(FAV-COLOR "Green" FAV-SEASON "Summer")

So I assume the direct assigning of a plist-like structure to Joe (assigning to the symbol Joes's value cell) isn't a truly supported data structure (like get, getf etc.) as it is with the symbol Joe's property list. Nor as an alist, which is always the value of a variable and has assoc, rassoc, etc. May I therefore conclude there really is no use of the plist concept in the real world besides the built-in symbol cell for property lists? So often in tutorials, plist is automatically described as the symbol's property list, and there is no further discussion of the concept.

I guess in a backwards way, I'm pursuing the rather vague, spotty idea of what are good, best-practice data structures in Lisp.


Solution

  • Use GETF to retrieve values from a list, which is a property list.

    CL-USER 141 > (let ((joe '(:fav-season  "Fall"
                               :fav-color  "Blue")))
                    (list (getf joe 'fav-color)
                          (getf joe :fav-color)))
    (NIL "Blue")
    

    Notice that you need to get the indicator right.

    You've used GET, which can be implemented in terms of GETF:

    (defun get (x y)
      (getf (symbol-plist x) y))
    

    Thus one can use property lists not just in symbol property lists - there is a basic operator for it.

    Note also that there are many other data structures, which allow access to values via keys: assoc lists, CLOS classes, hash-tables. There are slightly different use cases for those.

    Property lists are often used when simple key and value data needs to be used in lists - for example in source code.

    Functions use property list like lists for keyword arguments, which one can manipulate:

    (let ((foo (list 'window :x 100 :y 200)))
       (setf (getf (rest foo) :x) 200)
       (apply #'make-instance foo))
    

    Sometimes property lists are added to CLOS classes or structures. Structures in Common Lisp may not be extensible at runtime - they can't be redefined with additional slots. So often some classes and structures have a properties slot, where one can at runtime add/remove/updated the key/value pairs.