diff options
author | Earl Hyatt <okamsn@protonmail.com> | 2025-03-12 23:01:49 -0400 |
---|---|---|
committer | Stefan Monnier <monnier@iro.umontreal.ca> | 2025-03-31 14:29:48 -0400 |
commit | e04d1dafc700813c835ae4e45af4e104c49e8875 (patch) | |
tree | 405296248ee9da13e065213d8f88cfe317a7bc81 /lisp/emacs-lisp | |
parent | a97a61b630624f5a6ec917db92e2985c56b20aa0 (diff) | |
download | emacs-e04d1dafc700813c835ae4e45af4e104c49e8875.tar.gz emacs-e04d1dafc700813c835ae4e45af4e104c49e8875.tar.bz2 emacs-e04d1dafc700813c835ae4e45af4e104c49e8875.zip |
Add cl-with-accessors
* lisp/emacs-lisp/cl-macs.el (cl-with-accessors): New macro.
* doc/misc/cl.texi (Structures): Mention the new macro.
* test/lisp/emacs-lisp/cl-macs-tests.el (cl-lib-struct-with-accessors):
New Test.
* etc/NEWS (New macro 'cl-with-accessors'.): Mention the macro.
This macro is useful when making repeated use of a structures accessor
functions, such as reading from a slot and then writing to a slot. It
is similar to 'with-slots' from EIEIO, but uses accessor functions
instead of slot names.
Diffstat (limited to 'lisp/emacs-lisp')
-rw-r--r-- | lisp/emacs-lisp/cl-macs.el | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el index 960f2e6742b..cc1c6a6a5ad 100644 --- a/lisp/emacs-lisp/cl-macs.el +++ b/lisp/emacs-lisp/cl-macs.el @@ -2576,6 +2576,50 @@ See also `macroexp-let2'." collect `(,(car name) ,gensym)) ,@body))))) +;;;###autoload +(defmacro cl-with-accessors (bindings instance &rest body) + "Use BINDINGS as function calls on INSTANCE inside BODY. + +This macro helps when writing code that makes repeated use of the +accessor functions of a structure or object instance, such as those +created by `cl-defstruct' and `defclass'. + +BINDINGS is a list of (NAME ACCESSOR) pairs. Inside BODY, NAME is +treated as the function call (ACCESSOR INSTANCE) using +`cl-symbol-macrolet'. NAME can be used with `setf' and `setq' as a +generalized variable. Because of how the accessor is used, +`cl-with-accessors' can be used with any generalized variable that can +take a single argument, such as `car' and `cdr'. + +See also the macro `with-slots' described in the Info +node `(eieio)Accessing Slots', which is similar, but uses slot names +instead of accessor functions. + +\(fn ((NAME ACCESSOR) ...) INSTANCE &rest BODY)" + (declare (debug [(&rest (symbolp symbolp)) form body]) + (indent 2)) + (cond ((null body) + (macroexp-warn-and-return "`cl-with-accessors' used with empty body" + nil 'empty-body)) + ((null bindings) + (macroexp-warn-and-return "`cl-with-accessors' used without accessors" + (macroexp-progn body) + 'suspicious)) + (t + (cl-once-only (instance) + (let ((symbol-macros)) + (dolist (b bindings) + (pcase b + (`(,(and (pred symbolp) var) + ,(and (pred symbolp) accessor)) + (push `(,var (,accessor ,instance)) + symbol-macros)) + (_ + (error "Malformed `cl-with-accessors' binding: %S" b)))) + `(cl-symbol-macrolet + ,symbol-macros + ,@body)))))) + ;;; Multiple values. ;;;###autoload |