define-modify-macro
define-modify-macro Macro
Syntax:
define-modify-macro name lambda-list function [documentation] ! name
Arguments and Values:
name—a symbol.
lambda-list—a define-modify-macro lambda list
function—a symbol.
documentation—a string; not evaluated.
Description:
define-modify-macro defines a macro named name to read and write a place.
The arguments to the new macro are a place, followed by the arguments that are supplied in lambda-list. Macros defined with define-modify-macro correctly pass the environment parameter to get-setf-expansion.
When the macro is invoked, function is applied to the old contents of the place and the lambda-list arguments to obtain the new value, and the place is updated to contain the result.
Except for the issue of avoiding multiple evaluation (see below), the expansion of a define-modify-macro is equivalent to the following:
(defmacro name (reference . lambda-list)
documentation
‘(setf ,reference
(function ,reference ,arg1 ,arg2 ...)))
where arg1, arg2, ..., are the parameters appearing in lambda-list; appropriate provision is made for a rest parameter .
The subforms of the macro calls defined by define-modify-macro are evaluated as specified in Section 5.1.1.1 (Evaluation of Subforms to Places).
Documentation is attached as a documentation string to name (as kind function) and to the macro function.
If a define-modify-macro form appears as a top level form, the compiler must store the macro definition at compile time, so that occurrences of the macro later on in the file can be expanded correctly.
Examples:
(define-modify-macro appendf (&rest args)
append "Append onto list") *!* APPENDF
(setq x ’(a b c) y x) *!* (A B C)
(appendf x ’(d e f) ’(1 2 3)) *!* (A B C D E F 1 2 3)
x *!* (A B C D E F 1 2 3)
y *!* (A B C)
(define-modify-macro new-incf (&optional (delta 1)) +)
(define-modify-macro unionf (other-set &rest keywords) union)
Side Eects:
A macro definition is assigned to name.
See Also:
defsetf, define-setf-expander, documentation, Section 3.4.11 (Syntactic Interaction of Documentation Strings and Declarations)
Expanded Reference: define-modify-macro
Defining appendf
define-modify-macro creates a macro that reads a place, applies a function, and stores the result back. This is the easiest way to define simple modify macros.
;; appendf appends items to the list stored in a place
(define-modify-macro appendf (&rest lists) append
"Append lists to the value stored in the place.")
(let ((items '(1 2 3)))
(appendf items '(4 5) '(6))
items)
=> (1 2 3 4 5 6)
Defining togglef for Booleans
A toggle macro flips a generalized boolean in place.
(define-modify-macro togglef () not
"Toggle a boolean place.")
(let ((flag t))
(togglef flag)
flag)
=> NIL
(let ((flag nil))
(togglef flag)
flag)
=> T
Defining multf for Numeric Places
You can define modify macros for any two-argument function that takes the current value as its first argument.
;; multf multiplies a numeric place by a factor
(define-modify-macro multf (&rest args) *
"Multiply the value in the place.")
(let ((price 100))
(multf price 1.1)
price)
=> 110.0
Works with Generalized Places
Modify macros defined with define-modify-macro work with any setf-able place, not just variables.
(define-modify-macro nconcf (&rest lists) nconc)
(let ((alist (list (cons :a (list 1 2)))))
(nconcf (cdr (assoc :a alist)) (list 3 4))
alist)
=> ((:A 1 2 3 4))