diff options
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 |