emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

oref* and with-slots* macros


From: Adam Porter
Subject: oref* and with-slots* macros
Date: Sat, 26 May 2018 05:26:32 -0500

Hi,

I came up with these EIEIO-related macros a while back to help the
clarity of some code I was writing.  They seem generally useful enough
that I think it would be good to add them to Emacs itself, rather than
distributing them in a package on ELPA or MELPA.

+ `oref*' accesses slots of nested EIEIO objects.  For example, instead of:

        (oref (oref room :connection) :connect-time)

    You can write:

        (oref* room :connection :connect-time)

+ `with-slots*' allows access to nested EIEIO objects' slots.  For
  example, instead of:

        (with-slots (id session) room
          (with-slots (user) session
            user))

    You can write:

        (with-slots* (((id session) room)
                      ((user) session))
                     user)

    This is also possible using `pcase-let*` with its "eieio" type, but
    `with-slots*' is a bit simpler when only accessing object slots.

The source for these macros is below.  If the Emacs devs agree that
these should be added, I'll be happy to submit a patch with whatever
changes are desired.

Thanks,
Adam Porter

#+BEGIN_SRC elisp
(defmacro oref* (&rest slots)
  "Access SLOTS of nested EIEIO objects.
The first of SLOTS should be an object, while the rest should be
slot symbols.  Accessing each slot should return an object for
which the next slot is valid, except for the last slot, which may
return any value."
  (cl-labels ((rec (slots)
                   `(oref ,(if (and (consp (cdr slots))
                                    (cddr slots))
                               (rec (cdr slots))
                             (cadr slots))
                          ,(car slots))))
    (rec (nreverse slots))))

(defmacro with-slots* (slots-objects &rest body)
  "Access slots of nested objects, evaluating BODY.
Creates nested `with-slots' forms, so each slot is a generalized
variable.  For example:

\(with-slots* (((id session) room)
              ((user) session))
             user)

Is transformed to:

\(with-slots (id session) room
  (with-slots (user) session
    user))"
  (declare (indent defun))
  (cl-loop for (slots object) in (nreverse slots-objects)
           do (setq body `((with-slots ,slots ,object ,@body)))
           finally return (car body)))
#+END_SRC



reply via email to

[Prev in Thread] Current Thread [Next in Thread]