eval

We could get around this problem by requiring the caller to quote every argument to limited-save-excursion:

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

This time limited-save-excursion is called with the two arguments (beginning-of-line) and (point). It could record the value of point, explicitly evaluate each subexpression in turn, then restore point and return. It would look like the following example.

(defun limited-save-excursion (&rest exprs)
  "Like save-excursion, but only restores point."
  (let ((saved-point (point)))     ;memorize point
    (while exprs
      (eval (car exprs))           ;evaluate the next argument
      (setq exprs (cdr exprs)))
    (goto-char saved-point)))      ;restore point

This function contains something new: a call to eval, which takes a Lisp expression as an argument and evaluates it. At first that may not seem like much since, after all, the Lisp interpreter is already evaluating Lisp expressions automatically, with no calls to eval needed. But sometimes the result of evaluation is another Lisp expression which you'd like to evaluate, and Lisp won't do the second one automatically. If we were to execute only (car exprs), we'd be extracting the first subexpression, then discarding it! We need eval to make that subexpression do something useful once we have it.

Here's an simple example to illustrate the difference between the evaluation that Emacs does normally and the need for eval:

(setq x '(+ 3 5))
x ⇒ (+ 3 5)       ;evaluating x
(eval x) ⇒ 8      ;evaluating the value of x

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.