Code: Select all
(define-setf-expander if (test then &optional else)
"Lets you use IF as the place of a setf form.
For example (setf (if test a b) 7). In the example,
a will be set to 7 if test returns true, otherwise
b will be set to 7.
The then and (optional) else forms must be places."
(let ((new-value (gensym)))
(values ()
()
`(,new-value)
`(if ,test (setf ,then ,new-value)
,(if else `(setf ,else ,new-value) new-value))
`(if ,test ,then ,@(when else `(,else))))))
It lets you write:
Code: Select all
(setf (if <test> <place-a> <place-b>) <new-value-form>)
Code: Select all
(if <test>
(setf <place-a> <new-value-form>)
(setf <place-b> <new-value-form>))
Here's an example of the power of this feature of CL - the setf expansion being used by pop (it can also be used by incf, decf, etc.):
Code: Select all
(let ((a (list 1 2 3)) (b (list 4 5 6)))
(print (pop (if (zerop (random 2)) a b)))
(list a b))