From 35c893ddaf21b93677850a69709b59630bb0feb7 Mon Sep 17 00:00:00 2001 From: Mark Oteiza Date: Tue, 12 Sep 2017 11:08:00 -0400 Subject: [PATCH] Move gensym to core Elisp * doc/lispref/symbols.texi (Creating Symbols): Mention gensym right after make-symbol. * etc/NEWS: Mention. * lisp/emacs-lisp/cl-macs.el (cl--gensym-counter): Alias to gensym-counter. (cl-gensym): Alias to gensym. * lisp/emacs-lisp/cl.el: Remove gensym from list of aliases. * lisp/emacs-lisp/edebug.el (edebug-make-enter-wrapper): * lisp/emacs-lisp/ert-x.el (ert-with-message-capture): (ert--expand-should-1, ert--expand-should): (ert--should-error-handle-error): * lisp/emacs-lisp/generator.el (cps--gensym): * lisp/emacs-lisp/gv.el (setf): * lisp/emacs-lisp/inline.el (inline--do-letlisteval): * lisp/emacs-lisp/pcase.el (pcase--make-docstring, pcase-dolist): (pcase--funcall, pcase--u1): Use gensym. * lisp/subr.el (gensym-counter): New variable. (gensym): New function, assimilated from cl-lib. --- doc/lispref/symbols.texi | 7 +++++++ etc/NEWS | 3 +++ lisp/emacs-lisp/cl-macs.el | 11 ++--------- lisp/emacs-lisp/cl.el | 1 - lisp/emacs-lisp/edebug.el | 2 +- lisp/emacs-lisp/ert-x.el | 2 +- lisp/emacs-lisp/ert.el | 18 +++++++++--------- lisp/emacs-lisp/generator.el | 5 +---- lisp/emacs-lisp/gv.el | 4 ++-- lisp/emacs-lisp/inline.el | 2 +- lisp/emacs-lisp/pcase.el | 8 ++++---- lisp/subr.el | 14 ++++++++++++++ 12 files changed, 45 insertions(+), 32 deletions(-) diff --git a/doc/lispref/symbols.texi b/doc/lispref/symbols.texi index e6ea8a1cc09..2d9ec6fda30 100644 --- a/doc/lispref/symbols.texi +++ b/doc/lispref/symbols.texi @@ -273,6 +273,13 @@ distinct uninterned symbol whose name is also @samp{foo}. @end example @end defun +@defun gensym &optional prefix +This function returns a symbol using @code{make-symbol}, whose name is +made by appending @code{gensym-counter} to @var{prefix}. The prefix +defaults to @code{"G"}. If @var{prefix} is a number, it replaces the +value of the counter. +@end defun + @defun intern name &optional obarray This function returns the interned symbol whose name is @var{name}. If there is no such symbol in the obarray @var{obarray}, @code{intern} diff --git a/etc/NEWS b/etc/NEWS index 3f1df23ec30..af29b29264d 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1525,6 +1525,9 @@ It avoids unnecessary consing (and garbage collection). +++ ** 'car' and 'cdr' compositions 'cXXXr' and 'cXXXXr' are now part of Elisp. ++++ +** 'gensym' is now part of Elisp. + --- ** 'if-let*', 'when-let*', and 'and-let*' are new in subr-x.el. The incumbent 'if-let' and 'when-let' are now aliases. diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el index 3405c92e8d4..eee5953882d 100644 --- a/lisp/emacs-lisp/cl-macs.el +++ b/lisp/emacs-lisp/cl-macs.el @@ -161,16 +161,9 @@ whether X is known at compile time, macroexpand it completely in ;;; Symbols. -(defvar cl--gensym-counter 0) +(defvaralias 'cl--gensym-counter 'gensym-counter) ;;;###autoload -(defun cl-gensym (&optional prefix) - "Generate a new uninterned symbol. -The name is made by appending a number to PREFIX, default \"G\"." - (let ((pfix (if (stringp prefix) prefix "G")) - (num (if (integerp prefix) prefix - (prog1 cl--gensym-counter - (setq cl--gensym-counter (1+ cl--gensym-counter)))))) - (make-symbol (format "%s%d" pfix num)))) +(cl--defalias 'cl-gensym 'gensym) (defvar cl--gentemp-counter 0) ;;;###autoload diff --git a/lisp/emacs-lisp/cl.el b/lisp/emacs-lisp/cl.el index 73eb9a4e866..306237ca38f 100644 --- a/lisp/emacs-lisp/cl.el +++ b/lisp/emacs-lisp/cl.el @@ -250,7 +250,6 @@ eval-when destructuring-bind gentemp - gensym pairlis acons subst diff --git a/lisp/emacs-lisp/edebug.el b/lisp/emacs-lisp/edebug.el index c6ef8d7a99c..3190346497d 100644 --- a/lisp/emacs-lisp/edebug.el +++ b/lisp/emacs-lisp/edebug.el @@ -1193,7 +1193,7 @@ circular objects. Let `read' read everything else." ;; Uses the dynamically bound vars edebug-def-name and edebug-def-args. ;; Do this after parsing since that may find a name. (setq edebug-def-name - (or edebug-def-name edebug-old-def-name (cl-gensym "edebug-anon"))) + (or edebug-def-name edebug-old-def-name (gensym "edebug-anon"))) `(edebug-enter (quote ,edebug-def-name) ,(if edebug-inside-func diff --git a/lisp/emacs-lisp/ert-x.el b/lisp/emacs-lisp/ert-x.el index 4cf9d9609e9..1413b9cd0bf 100644 --- a/lisp/emacs-lisp/ert-x.el +++ b/lisp/emacs-lisp/ert-x.el @@ -295,7 +295,7 @@ This is useful for separating the issuance of messages by the code under test from the behavior of the *Messages* buffer." (declare (debug (symbolp body)) (indent 1)) - (let ((g-advice (cl-gensym))) + (let ((g-advice (gensym))) `(let* ((,var "") (,g-advice (lambda (func &rest args) (if (or (null args) (equal (car args) "")) diff --git a/lisp/emacs-lisp/ert.el b/lisp/emacs-lisp/ert.el index 9cc764d78e0..579e5e0aadc 100644 --- a/lisp/emacs-lisp/ert.el +++ b/lisp/emacs-lisp/ert.el @@ -298,8 +298,8 @@ It should only be stopped when ran from inside ert--run-test-internal." (error `(signal ',(car err) ',(cdr err)))))) (cond ((or (atom form) (ert--special-operator-p (car form))) - (let ((value (cl-gensym "value-"))) - `(let ((,value (cl-gensym "ert-form-evaluation-aborted-"))) + (let ((value (gensym "value-"))) + `(let ((,value (gensym "ert-form-evaluation-aborted-"))) ,(funcall inner-expander `(setq ,value ,form) `(list ',whole :form ',form :value ,value) @@ -312,10 +312,10 @@ It should only be stopped when ran from inside ert--run-test-internal." (and (consp fn-name) (eql (car fn-name) 'lambda) (listp (cdr fn-name))))) - (let ((fn (cl-gensym "fn-")) - (args (cl-gensym "args-")) - (value (cl-gensym "value-")) - (default-value (cl-gensym "ert-form-evaluation-aborted-"))) + (let ((fn (gensym "fn-")) + (args (gensym "args-")) + (value (gensym "value-")) + (default-value (gensym "ert-form-evaluation-aborted-"))) `(let* ((,fn (function ,fn-name)) (,args (condition-case err (let ((signal-hook-function #'ert--should-signal-hook)) @@ -357,7 +357,7 @@ FORM-DESCRIPTION-FORM before it has called INNER-FORM." (ert--expand-should-1 whole form (lambda (inner-form form-description-form value-var) - (let ((form-description (cl-gensym "form-description-"))) + (let ((form-description (gensym "form-description-"))) `(let (,form-description) ,(funcall inner-expander `(unwind-protect @@ -435,8 +435,8 @@ failed." `(should-error ,form ,@keys) form (lambda (inner-form form-description-form value-var) - (let ((errorp (cl-gensym "errorp")) - (form-description-fn (cl-gensym "form-description-fn-"))) + (let ((errorp (gensym "errorp")) + (form-description-fn (gensym "form-description-fn-"))) `(let ((,errorp nil) (,form-description-fn (lambda () ,form-description-form))) (condition-case -condition- diff --git a/lisp/emacs-lisp/generator.el b/lisp/emacs-lisp/generator.el index c96b400809b..fe5d2d0728f 100644 --- a/lisp/emacs-lisp/generator.el +++ b/lisp/emacs-lisp/generator.el @@ -86,10 +86,7 @@ (defvar cps--cleanup-function nil) (defmacro cps--gensym (fmt &rest args) - ;; Change this function to use `cl-gensym' if you want the generated - ;; code to be easier to read and debug. - ;; (cl-gensym (apply #'format fmt args)) - `(progn (ignore ,@args) (make-symbol ,fmt))) + `(gensym (format ,fmt ,@args))) (defvar cps--dynamic-wrappers '(identity) "List of transformer functions to apply to atomic forms we diff --git a/lisp/emacs-lisp/gv.el b/lisp/emacs-lisp/gv.el index a8b8974cb4f..42b1c216956 100644 --- a/lisp/emacs-lisp/gv.el +++ b/lisp/emacs-lisp/gv.el @@ -431,7 +431,7 @@ The return value is the last VAL in the list. ;; code is large, but otherwise results in more efficient code. `(if ,test ,(gv-get then do) ,@(macroexp-unprogn (gv-get (macroexp-progn else) do))) - (let ((v (make-symbol "v"))) + (let ((v (gensym "v"))) (macroexp-let2 nil gv `(if ,test ,(gv-letplace (getter setter) then `(cons (lambda () ,getter) @@ -456,7 +456,7 @@ The return value is the last VAL in the list. (gv-get (macroexp-progn (cdr branch)) do))) (gv-get (car branch) do))) branches)) - (let ((v (make-symbol "v"))) + (let ((v (gensym "v"))) (macroexp-let2 nil gv `(cond ,@(mapcar diff --git a/lisp/emacs-lisp/inline.el b/lisp/emacs-lisp/inline.el index ce46f66aef8..cf8e2f22d88 100644 --- a/lisp/emacs-lisp/inline.el +++ b/lisp/emacs-lisp/inline.el @@ -218,7 +218,7 @@ After VARS is handled, BODY is evaluated in the new environment." `(let* ((,bsym ()) (,listvar (mapcar (lambda (e) (if (macroexp-copyable-p e) e - (let ((v (make-symbol "v"))) + (let ((v (gensym "v"))) (push (list v e) ,bsym) v))) ,listvar))) diff --git a/lisp/emacs-lisp/pcase.el b/lisp/emacs-lisp/pcase.el index 253b60e7534..5935845743d 100644 --- a/lisp/emacs-lisp/pcase.el +++ b/lisp/emacs-lisp/pcase.el @@ -213,7 +213,7 @@ Emacs Lisp manual for more information and examples." (defmacro pcase-exhaustive (exp &rest cases) "The exhaustive version of `pcase' (which see)." (declare (indent 1) (debug pcase)) - (let* ((x (make-symbol "x")) + (let* ((x (gensym "x")) (pcase--dontwarn-upats (cons x pcase--dontwarn-upats))) (pcase--expand ;; FIXME: Could we add the FILE:LINE data in the error message? @@ -304,7 +304,7 @@ any kind of error." (declare (indent 1) (debug ((pcase-PAT form) body))) (if (pcase--trivial-upat-p (car spec)) `(dolist ,spec ,@body) - (let ((tmpvar (make-symbol "x"))) + (let ((tmpvar (gensym "x"))) `(dolist (,tmpvar ,@(cdr spec)) (pcase-let* ((,(car spec) ,tmpvar)) ,@body))))) @@ -715,7 +715,7 @@ MATCH is the pattern that needs to be matched, of the form: (call (progn (when (memq arg vs) ;; `arg' is shadowed by `env'. - (let ((newsym (make-symbol "x"))) + (let ((newsym (gensym "x"))) (push (list newsym arg) env) (setq arg newsym))) (if (functionp fun) @@ -842,7 +842,7 @@ Otherwise, it defers to REST which is a list of branches of the form ;; A upat of the form (app FUN PAT) (pcase--mark-used sym) (let* ((fun (nth 1 upat)) - (nsym (make-symbol "x")) + (nsym (gensym "x")) (body ;; We don't change `matches' to reuse the newly computed value, ;; because we assume there shouldn't be such redundancy in there. diff --git a/lisp/subr.el b/lisp/subr.el index 2ad52f6a638..ebb8b53b502 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -280,6 +280,20 @@ without silencing all errors." ;;;; Basic Lisp functions. +(defvar gensym-counter 0 + "Number used to construct the name of the next symbol created by `gensym'.") + +(defun gensym (&optional prefix) + "Return a new uninterned symbol. +The name is made by appending `gensym-counter' to PREFIX. +PREFIX can be a string, and defaults to \"G\". +If PREFIX is a number, it replaces the value of `gensym-counter'." + (let ((pfix (if (stringp prefix) prefix "G")) + (num (if (integerp prefix) prefix + (prog1 gensym-counter + (setq gensym-counter (1+ gensym-counter)))))) + (make-symbol (format "%s%d" pfix num)))) + (defun ignore (&rest _ignore) "Do nothing and return nil. This function accepts any number of arguments, but ignores them."