Skip to content

Instantly share code, notes, and snippets.

@jdtsmith
Last active November 5, 2022 00:49
Show Gist options
  • Save jdtsmith/5bc37c269dec2436725fd2e1fa788a54 to your computer and use it in GitHub Desktop.
Save jdtsmith/5bc37c269dec2436725fd2e1fa788a54 to your computer and use it in GitHub Desktop.
Using `cl-defstruct` structure with `cl-macrolet-symbol` for very convenient read/write access to structure slots by name.
(defmacro with-convenient-slots (slots obj &rest body)
"Convenience wrapper for read/write access to struct data.
Bind slot names SLOTS (a list) within the `my-struct'
record OBJ, and execute BODY."
`(cl-symbol-macrolet
,(cl-loop for slot in slots
collect `(,slot (,(intern (concat "my-struct-"
(symbol-name slot)))
,obj)))
,@body))
;; Example usage
(cl-defstruct my-struct "A struct" foo bar)
(setq myobj (make-my-struct :foo 1 :bar 2))
(with-convenient-slots (foo bar) myobj
(setq foo (+ 123 bar)
bar (+ 456 foo)))
;; Original version: more general, but less efficient
(defmacro with-convenient-slots (slots obj &rest body)
"Convenience wrapper for read/write access to struct data.
Bind slot names SLOTS (a list) within the `some-data-type'
record OBJ, and execute BODY."
(declare (indent 2))
`(cl-symbol-macrolet
,(cl-loop for slot in slots
collect `(,slot (cl-struct-slot-value
'my-struct
',slot ,obj)))
,@body))
@alphapapa
Copy link

alphapapa commented Nov 5, 2022

The code cleanup for reasonable size functions with well named slots makes it well worth it I think.

It depends on a variety of factors. Another cost is to code readability: when other programmers are reading your code, the more non-standard macros used in the code, the heavier the cognitive load is to understand the code.

What approaches do you use to keep structs under control?

I don't suppose that I use any, really, other than to try to keep the package name prefix and slot names short. The package I use them in the most thoroughly is https://github.com/alphapapa/ement.el. There are a few places where having a place-setting macro would be helpful, but it doesn't seem to be a big deal. I also use highlight-function-calls-mode, which shows function names (including accessors) in a different face, which helps visually identify them and confirm that they are typed correctly, and I would miss that if I used such a macro instead.

RE pcase-let, I didn't see your post but it's an interesting idea: pcase-symbol-macrolet?

Hm, maybe so, or maybe pcase-letf, to coincide with cl-letf. But I'm doubtful that such a macro would be accepted into Emacs core, anyway. It would probably take some wrangling!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment