LISP - Symbols
Lisp - Symbols and Property Lists
Section titled “Lisp - Symbols and Property Lists”In Common Lisp, a symbol is a unique, named data object. It’s not just a name for a variable; the symbol itself is an object that can be manipulated. Think of it as a named container that can hold a value, a function, and a list of properties all at once.
One of the classic features of symbols is the property list, or plist. A plist is a simple key-value store attached directly to a symbol, allowing you to associate arbitrary metadata with it.
Understanding Property Lists
Section titled “Understanding Property Lists”A property list is structured as a list of alternating keys (called indicators) and values. For example, if we want to describe a person, we could use a symbol 'person and attach properties like age, job, and city.
When a symbol is first created, its property list is empty. You can add or modify properties using the get function inside a setf form. setf is Lisp’s universal assignment operator, capable of modifying many different kinds of places.
Let’s see how to assign properties to a symbol named book.
Example: Creating and Accessing Properties
Section titled “Example: Creating and Accessing Properties”Create a new source file named main.lisp and enter the following code. This example demonstrates setting and then retrieving properties from the book symbol.
main.lisp
Section titled “main.lisp”;;; Use SETF with GET to assign properties to the 'book symbol.;;; Note that both the symbol ('book) and the indicators ('title, etc.) are quoted.(setf (get 'book 'title) "Gone with the Wind")(setf (get 'book 'author) "Margaret Mitchell")(setf (get 'book 'publisher) "Warner Books")
;;; Use GET to retrieve the value for a specific property.(format t "Title: ~s~%" (get 'book 'title))(format t "Author: ~s~%" (get 'book 'author))
;;; GET returns NIL if the property does not exist.(format t "ISBN: ~s~%" (get 'book 'isbn))Output
Section titled “Output”When you load and execute the code (e.g., in an SBCL REPL with (load "main.lisp")), it produces the following result:
Title: "Gone with the Wind"Author: "Margaret Mitchell"ISBN: NILManaging Property Lists
Section titled “Managing Property Lists”Common Lisp provides a few key functions for managing plists.
get symbol indicator &optional default: Retrieves the value for the givenindicator. If not found, it returnsNILor the provideddefaultvalue.symbol-plist symbol: Returns the entire property list of the symbol.remprop symbol indicator: Removes a property (both key and value) from the symbol’s plist.
Example: Inspecting and Removing Properties
Section titled “Example: Inspecting and Removing Properties”Let’s expand on our previous example to see these functions in action.
main.lisp
Section titled “main.lisp”;; Define a function to set up and demonstrate properties for a symbol.(defun demonstrate-plists (person-symbol) (setf (get person-symbol 'age) 43) (setf (get person-symbol 'job) "Accountant") (setf (get person-symbol 'sex) 'female)
(format t "Initial plist for '~s: ~s~%" person-symbol (symbol-plist person-symbol))
;; Remove the 'age' property (remprop person-symbol 'age) (format t "After removing 'age: ~s~%" (symbol-plist person-symbol)))
;; Run the demonstration with the symbol 'annie(demonstrate-plists 'annie)Output
Section titled “Output”Initial plist for 'ANNIE: (SEX FEMALE JOB "Accountant" AGE 43)After removing 'age: (SEX FEMALE JOB "Accountant")Modern Best Practices: Plists vs. Other Structures
Section titled “Modern Best Practices: Plists vs. Other Structures”While property lists are a classic Lisp feature, for modeling structured application data, modern Common Lisp offers better alternatives:
- Hash Tables: Ideal for general-purpose key-value mapping where keys are not necessarily symbols. They are highly efficient.
(make-hash-table) - Structs: A lightweight way to define simple object-like structures with named slots. They offer better performance and type-checking than plists.
(defstruct) - CLOS Classes: The full Common Lisp Object System provides powerful features like inheritance, multi-methods, and introspection.
(defclass)
When should you use plists? Property lists are best suited for attaching metadata to symbols themselves, especially in metaprogramming or compiler-related tasks. For representing entities like books or users in your application, prefer defstruct for simplicity or defclass for more complex requirements.
Example: The defstruct Alternative
Section titled “Example: The defstruct Alternative”;; Defining a book structure(defstruct book title author publisher isbn)
;; Creating an instance of the book struct(let ((my-book (make-book :title "Structure and Interpretation of Computer Programs" :author "Abelson & Sussman" :publisher "MIT Press")))
;; Accessing slots is clean and efficient (format t "Struct Title: ~s~%" (book-title my-book)) (format t "Struct Author: ~s~%" (book-author my-book)))Output
Section titled “Output”Struct Title: "Structure and Interpretation of Computer Programs"Struct Author: "Abelson & Sussman"