diff options
Diffstat (limited to 'doc/misc/cl.texi')
-rw-r--r-- | doc/misc/cl.texi | 174 |
1 files changed, 95 insertions, 79 deletions
diff --git a/doc/misc/cl.texi b/doc/misc/cl.texi index 4eb3d85d2ba..a6747b1096a 100644 --- a/doc/misc/cl.texi +++ b/doc/misc/cl.texi @@ -444,7 +444,7 @@ the ``rest'' argument is bound to the keyword list as it appears in the call. For example: @example -(cl-defun find-thing (thing &rest rest &key need &allow-other-keys) +(cl-defun find-thing (thing thing-list &rest rest &key need &allow-other-keys) (or (apply 'cl-member thing thing-list :allow-other-keys t rest) (if need (error "Thing not found")))) @end example @@ -843,6 +843,7 @@ constructs. * Iteration:: @code{cl-do}, @code{cl-dotimes}, @code{cl-dolist}, @code{cl-do-symbols}. * Loop Facility:: The Common Lisp @code{loop} macro. * Multiple Values:: @code{cl-values}, @code{cl-multiple-value-bind}, etc. +* Macro-Writing Macros:: @code{cl-with-gensyms}, @code{cl-once-only}. @end menu @node Assignment @@ -919,69 +920,6 @@ cl-caaar@dots{}cl-cddddr cl-first@dots{}cl-tenth Note that for @code{cl-getf} (as for @code{nthcdr}), the list argument of the function must itself be a valid @var{place} form. -@item -General Emacs Lisp functions: -@example -buffer-file-name getenv -buffer-modified-p global-key-binding -buffer-name local-key-binding -buffer-string mark -buffer-substring mark-marker -current-buffer marker-position -current-case-table mouse-position -current-column point -current-global-map point-marker -current-input-mode point-max -current-local-map point-min -current-window-configuration read-mouse-position -default-file-modes screen-height -documentation-property screen-width -face-background selected-window -face-background-pixmap selected-screen -face-font selected-frame -face-foreground standard-case-table -face-underline-p syntax-table -file-modes visited-file-modtime -frame-height window-height -frame-parameters window-width -frame-visible-p x-get-secondary-selection -frame-width x-get-selection -get-register -@end example - -Most of these have directly corresponding ``set'' functions, like -@code{use-local-map} for @code{current-local-map}, or @code{goto-char} -for @code{point}. A few, like @code{point-min}, expand to longer -sequences of code when they are used with @code{setf} -(@code{(narrow-to-region x (point-max))} in this case). - -@item -A call of the form @code{(substring @var{subplace} @var{n} [@var{m}])}, -where @var{subplace} is itself a valid generalized variable whose -current value is a string, and where the value stored is also a -string. The new string is spliced into the specified part of the -destination string. For example: - -@example -(setq a (list "hello" "world")) - @result{} ("hello" "world") -(cadr a) - @result{} "world" -(substring (cadr a) 2 4) - @result{} "rl" -(setf (substring (cadr a) 2 4) "o") - @result{} "o" -(cadr a) - @result{} "wood" -a - @result{} ("hello" "wood") -@end example - -The generalized variable @code{buffer-substring}, listed above, -also works in this way by replacing a portion of the current buffer. - -@c FIXME? Also 'eq'? (see cl-lib.el) - @c Currently commented out in cl.el. @ignore @item @@ -1245,6 +1183,12 @@ blocks for other macros like @code{cl-incf}, and @code{cl-pushnew}. The @code{cl-letf} and @code{cl-letf*} macros are used in the processing of symbol macros; @pxref{Macro Bindings}. +@defmac with-memoization @var{place} @var{code}@dots{} +This macro provides a simple way to do memoization. @var{code} is +evaluated and then stashed in @var{place}. If @var{place}'s value is +non-@code{nil}, return that value instead of evaluating @var{code}. +@end defmac + @node Variable Bindings @section Variable Bindings @@ -1374,19 +1318,10 @@ bar A @code{setq} of a symbol macro is treated the same as a @code{setf}. I.e., @code{(setq foo 4)} in the above would be equivalent to -@code{(setf foo 4)}, which in turn expands to @code{(setf (car bar) 4)}. - -Likewise, a @code{let} or @code{let*} binding a symbol macro is -treated like a @code{cl-letf} or @code{cl-letf*}. This differs from true -Common Lisp, where the rules of lexical scoping cause a @code{let} -binding to shadow a @code{symbol-macrolet} binding. In this package, -such shadowing does not occur, even when @code{lexical-binding} is -@c See https://debbugs.gnu.org/12119 -@code{t}. (This behavior predates the addition of lexical binding to -Emacs Lisp, and may change in future to respect @code{lexical-binding}.) -At present in this package, only @code{lexical-let} and -@code{lexical-let*} will shadow a symbol macro. @xref{Obsolete -Lexical Binding}. +@code{(setf foo 4)}, which in turn expands to @code{(setf (car bar) +4)}. A @code{let} (or @code{let*}, @code{lambda}, ...) binding of +the same symbol will locally shadow the symbol macro as is the case in +Common Lisp. There is no analogue of @code{defmacro} for symbol macros; all symbol macros are local. A typical use of @code{cl-symbol-macrolet} is in the @@ -2507,6 +2442,86 @@ in @code{cl-multiple-value-bind}. Since a perfect emulation is not feasible in Emacs Lisp, this package opts to keep it as simple and predictable as possible. +@node Macro-Writing Macros +@section Macro-Writing Macros + +@noindent +This package includes two classic Common Lisp macro-writing macros to +help render complex macrology easier to read. + +@defmac cl-with-gensyms names@dots{} body +This macro expands to code that executes @var{body} with each of the +variables in @var{names} bound to a fresh uninterned symbol, or +@dfn{gensym}, in Common Lisp parlance. For macros requiring more than +one gensym, use of @code{cl-with-gensyms} shortens the code and +renders one's intentions clearer. Compare: + +@example +(defmacro my-macro (foo) + (let ((bar (gensym "bar")) + (baz (gensym "baz")) + (quux (gensym "quux"))) + `(let ((,bar (+ @dots{}))) + @dots{}))) + +(defmacro my-macro (foo) + (cl-with-gensyms (bar baz quux) + `(let ((,bar (+ @dots{}))) + @dots{}))) +@end example +@end defmac + +@defmac cl-once-only ((variable form)@dots{}) body +This macro is primarily to help the macro programmer ensure that forms +supplied by the user of the macro are evaluated just once by its +expansion even though the result of evaluating the form is to occur +more than once. Less often, this macro is used to ensure that forms +supplied by the macro programmer are evaluated just once. + +Each @var{variable} may be used to refer to the result of evaluating +@var{form} in @var{body}. @code{cl-once-only} binds each +@var{variable} to a fresh uninterned symbol during the evaluation of +@var{body}. Then, @code{cl-once-only} wraps the final expansion in +code to evaluate each @var{form} and bind the result to the +corresponding uninterned symbol. Thus, when the macro writer +substitutes the value for @var{variable} into the expansion they are +effectively referring to the result of evaluating @var{form}, rather +than @var{form} itself. Another way to put this is that each +@var{variable} is bound to an expression for the (singular) result of +evaluating @var{form}. + +The most common case is where @var{variable} is one of the arguments +to the macro being written, so @code{(variable variable)} may be +abbreviated to just @code{variable}. + +For example, consider this macro: + +@example +(defmacro my-list (x y &rest forms) + (let ((x-result (gensym)) + (y-result (gensym))) + `(let ((,x-result ,x) + (,y-result ,y)) + (list ,x-result ,y-result ,x-result ,y-result + (progn ,@@forms)))) +@end example + +In a call like @w{@code{(my-list (pop foo) @dots{})}} the intermediate +binding to @code{x-result} ensures that the @code{pop} is not done +twice. But as a result the code is rather complex: the reader must +keep track of how @code{x-result} really just means the first +parameter of the call to the macro, and the required use of multiple +gensyms to avoid variable capture by @code{(progn ,@@forms)} obscures +things further. @code{cl-once-only} takes care of these details: + +@example +(defmacro my-list (x y &rest forms) + (cl-once-only (x y) + `(list ,x ,y ,x ,y + (progn ,@@forms)))) +@end example +@end defmac + @node Macros @chapter Macros @@ -2862,6 +2877,7 @@ out the property and value cells. @node Creating Symbols @section Creating Symbols +@cindex gensym @noindent These functions create unique symbols, typically for use as @@ -5014,13 +5030,13 @@ The above @code{incf} example could be written using @example (defmacro incf (place &optional n) (gv-letplace (getter setter) place - (macroexp-let2 nil v (or n 1) + (cl-once-only ((v (or n 1))) (funcall setter `(+ ,v ,getter))))) @end example @ignore (defmacro concatf (place &rest args) (gv-letplace (getter setter) place - (macroexp-let2 nil v (mapconcat 'identity args "") + (cl-once-only ((v `(mapconcat 'identity ',args))) (funcall setter `(concat ,getter ,v))))) @end ignore @end defmac |