"until" loop - My first elisp macro

Published on Dec 19, 2021, by Junji Zhi

Recently I was reading On Lisp by Paul Graham and got interested in using macros in Emacs Lisp. I decided to play with it.

Here’s my first macro: a until loop:

(defmacro until (test &rest body)
  `(while (not ,test)

Think of until as a negative while. The loop runs until the test becomes true.

To use it:

(setq jz/counter 1)
(setq jz/res '())
(until (>= jz/counter 5)
  (setq jz/counter (+ 1 jz/counter))
  (setq jz/res (cons jz/counter jz/res)))

;; jz/res => (5 4 3 2)

One note about defining macros: If we want to splice the rest of the lisp statement, we need two things:

  • Add a &rest in the macro argument List. It means that there are arbitrary number of statements there, and we wrap them all into body.
  • use comma-at, or ,@ to splice the body. It is similar to the spread operator ... in Javascript ES6 that can unwrap an object into another.

I’m not sure whether this is the most efficient way to define macros. But it definitely kicks off an interesting adventure!