Backquote and Unquote

Knowing that limited-save-excursion must be a macro function, all we have to do is imagine how a call to limited-save-excursion should expand. Here's a start:

(limited-save-excursion
  subexpr1
  subexpr2
  ...)

expands to

(let ((orig-point (point)))
  subexpr1
  subexpr2
  ...
  (goto-char orig-point))

Here's how to write that as a Lisp macro function:

(defmacro limited-save-excursion (&rest subexprs)
  "Like save-excursion, but only restores point."
  (append '(let ((orig-point (point))))
          subexprs
          '((goto-char orig-point))))

Remember that append works by effectively stripping off the outer parentheses of each list, gluing the results together, and putting a new pair of parentheses around the result. So this call to append takes three lists:

(let ((orig-point (point))))
(subexpr1 subexpr2 ...)
((goto-char orig-point))

strips off their outer parentheses:

let ((orig-point (point)))
subexpr1 subexpr2 ...
(goto-char orig-point)

and surrounds the result with new parentheses:

(let ((orig-point (point)))
  subexpr1
  subexpr2
  ...
  (goto-char orig-point))

That's the expansion of the macro, which then gets evaluated.

That would do the trick, but it's hard to read the macro definition and understand what's going on. Fortunately, there's a better way. It turns out that nearly all macros recombine their arguments with calls to such functions as list and append, with some expressions quoted and others not. In fact, that's so common that Emacs Lisp has a special syntax making it possible to write templates ...

Get Writing GNU Emacs Extensions now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.