Return Value

There's still a long way to go in developing limited-save-excursion. For one thing, it doesn't return the value of the last expression in subexprs, whereas save-excursion does. Instead, limited-save-excursion unhelpfully returns the value of (goto-char orig-point), which is the same as orig-point since goto-char returns its argument. This is particularly useless if you were expecting to do something like:

(setq line-start (limited-save-excursion
                   (beginning-of-line)
                   (point)))

To fix this problem, we must be sure to memorize the value of the last subexpression, then restore point, then return the memorized value. We might try this:

(defmacro limited-save-excursion (&rest subexprs)
  "Like save-excursion, but only restores point."
  `(let ((orig-point (point))
         (result (progn ,@subexprs)))
     (goto-char orig-point)
     result))

Note the use of progn, which simply executes everything passed to it and returns the value of its last argument—exactly what we need the result of the overall macro to be. However, this version is wrong for two reasons. The first reason has to do with the way let works. When this expression runs:

(let ((var1 val1)
      (var2 val2)
      ...
      (varn valn))
  body ...)

all the vals are evaluated before any of the vars are assigned, so no val may refer to any of the vars. Furthermore, the order in which they are evaluated is undefined. So, if we use the above version of limited-save-excursion to expand

(limited-save-excursion
  (beginning-of-line)
  (point))

into

(let ((orig-point (point)) ...

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.