Maybe I'm trying to be too creative here.
Is it possible to extend the concept of dynamic binding to SETF
able places of a dynamic variable, so that I can shadow part of a dynamic variable (such as a plist) with LET
bindings?
For example, I would like to be able to do something like:
(defparameter *foo* '(:one 1))
(let (((getf *foo* :one) 2))
(do-things))
To shadow the value of :one with 2.
This example doesn't work since (getf *foo* :one)
is not a variable name that LET
can assign a value to, but perhaps there is another way?
There is no standard way, but some implementations may offer
extensions, e.g., letf
.
Alternatively, you can use
unwind-protect
yourself:
(let ((old-value (getf *foo* :one)))
(unwind-protect
(progn (setf (getf *foo* :one) 2)
(do-things))
(setf (getf *foo* :one) old-value)))
If this is a common operation in your code, you might even define a macro for that:
(defmacro with-one (tmp-one &body body)
"Bind (getf *foo* :one) to tmp-one around body."
(let ((old-value (gensym "WITH-ONE-OLD")))
`(let ((,old-value (getf *foo* :one)))
(unwind-protect
(progn (setf (getf *foo* :one) ,tmp-one)
,@body)
(setf (getf *foo* :one) ,old-value)))))