aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Okay <colin@cicadas.surf>2022-10-12 11:37:12 -0500
committerColin Okay <colin@cicadas.surf>2022-10-12 11:37:12 -0500
commitd6463cdd25222c86975a7d49980bab94ed49857b (patch)
tree868df475eb73e56a47be3de40c6819051bb04f76
Add: with-plists; initial commit
-rw-r--r--derrida.asd10
-rw-r--r--derrida.lisp42
-rw-r--r--package.lisp5
3 files changed, 57 insertions, 0 deletions
diff --git a/derrida.asd b/derrida.asd
new file mode 100644
index 0000000..8527790
--- /dev/null
+++ b/derrida.asd
@@ -0,0 +1,10 @@
+;;;; derrida.asd
+
+(asdf:defsystem #:derrida
+ :description "Macros for desctructuring common data structures."
+ :author "Colin Okay <colin@cicadas.surf>"
+ :license "GPL-3.0"
+ :version "0.0.1"
+ :serial t
+ :components ((:file "package")
+ (:file "derrida")))
diff --git a/derrida.lisp b/derrida.lisp
new file mode 100644
index 0000000..ce1abeb
--- /dev/null
+++ b/derrida.lisp
@@ -0,0 +1,42 @@
+;;;; derrida.lisp
+
+(in-package #:derrida)
+
+(defmacro with-plist (keys plist &body body)
+ "KEYS is a list, each member of which is either a symbol or a pair of symbols.
+
+If a member is just a symbol, say KEY, then it is treated as the name
+of a symbol-macro (defined using symbol-macrolet) that expands to the
+expression (getf PLIST KEY). In this case, KEY is not allowed to be a
+keyword symbol.
+
+If a member is a pair of symbols, it is of the form (VAR KEY). Here,
+key is a valid key into the PLIST and VAR is the name of the symbol
+macrolet that will be bound to (getf PLIST KEY).
+
+EXAMPLE:
+
+(let ((pl
+ (list 'name \"colin\" :age 40 :|currentJob| :crumb-bum)))
+ (hq:with-plist (name (age :age) (job :|currentJob|)) pl
+ (setf age (1+ age))
+ (format t \"~a the ~a had a birthday, and is now ~a years old~%\"
+ name job age)
+ pl))
+
+The above would print out:
+colin the CRUMB-BUM had a birthday, and is now 41 years old
+
+And would return
+(NAME \"colin\" :AGE 41 :|currentJob| :CRUMB-BUM)"
+
+ (let* ((plist-var
+ (gensym))
+ (macrolet-bindings
+ (loop for term in keys
+ when (consp term )
+ collect (destructuring-bind (var key) term
+ `(,var (getf ,plist-var ',key)))
+ else
+ collect `(,term (getf ,plist-var ',term)))))
+ `(let ((,plist-var ,plist)) (symbol-macrolet ,macrolet-bindings ,@body))))
diff --git a/package.lisp b/package.lisp
new file mode 100644
index 0000000..33d3860
--- /dev/null
+++ b/package.lisp
@@ -0,0 +1,5 @@
+;;;; package.lisp
+
+(defpackage #:derrida
+ (:use #:cl)
+ (:export #:with-plist))