Commit 5e3fde03 authored by Paul Eggert's avatar Paul Eggert
Browse files

Improve docstring for macroexp-let2

* lisp/emacs-lisp/macroexp.el (macroexp-let2):
Improve as per suggestion by RMS in:
http://lists.gnu.org/archive/html/emacs-devel/2015-06/msg00621.html
Also, rename args to match new doc string.
parent 7baae811
......@@ -341,21 +341,44 @@ definitions to shadow the loaded ones for use in file byte-compilation."
((memq (car-safe then) '(if cond)) (macroexp-if `(not ,test) else then))
(t `(if ,test ,then ,else))))
(defmacro macroexp-let2 (test var exp &rest exps)
"Bind VAR to a copyable expression that returns the value of EXP.
This is like \\=`(let ((v ,EXP)) ,EXPS) except that `v' is a new generated
symbol which EXPS can find in VAR.
TEST should be the name of a predicate on EXP checking whether the `let' can
be skipped; if nil, as is usual, `macroexp-const-p' is used."
(defmacro macroexp-let2 (test sym exp &rest body)
"Evaluate BODY with SYM bound to an expression for EXP's value.
The intended usage is that BODY generates an expression that
will refer to EXP's value multiple times, but will evaluate
EXP only once. As BODY generates that expression, it should
use SYM to stand for the value of EXP.
If EXP is a simple, safe expression, then SYM's value is EXP itself.
Otherwise, SYM's value is a symbol which holds the value produced by
evaluating EXP. The return value incorporates the value of BODY, plus
additional code to evaluate EXP once and save the result so SYM can
refer to it.
If BODY consists of multiple forms, they are all evaluated
but only the last one's value matters.
TEST is a predicate to determine whether EXP qualifies as simple and
safe; if TEST is nil, only constant expressions qualify.
Example:
(macroexp-let2 nil foo EXP
\\=`(* ,foo ,foo))
generates an expression that evaluates EXP once,
then returns the square of that value.
You could do this with
(let ((foovar EXP))
(* foovar foovar))
but using `macroexp-let2' produces more efficient code in
cases where EXP is a constant."
(declare (indent 3) (debug (sexp sexp form body)))
(let ((bodysym (make-symbol "body"))
(expsym (make-symbol "exp")))
`(let* ((,expsym ,exp)
(,var (if (funcall #',(or test #'macroexp-const-p) ,expsym)
,expsym (make-symbol ,(symbol-name var))))
(,bodysym ,(macroexp-progn exps)))
(if (eq ,var ,expsym) ,bodysym
(macroexp-let* (list (list ,var ,expsym))
(,sym (if (funcall #',(or test #'macroexp-const-p) ,expsym)
,expsym (make-symbol ,(symbol-name sym))))
(,bodysym ,(macroexp-progn body)))
(if (eq ,sym ,expsym) ,bodysym
(macroexp-let* (list (list ,sym ,expsym))
,bodysym)))))
(defmacro macroexp-let2* (test bindings &rest body)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment