From: Stefan Kangas Date: Mon, 24 Feb 2025 23:12:00 +0000 (+0100) Subject: Make cl-gensym obsolete in favor of built-in gensym X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=8a8016b1dccfbbe1e9c36a865dae37395febfbe6;p=emacs.git Make cl-gensym obsolete in favor of built-in gensym * lisp/emacs-lisp/cl-macs.el (cl-gensym): Declare function obsolete in favor of gensym, added in Emacs 26.1. The only reason for its existence is that it allows an integer argument, but that's not really useful, so it's better to remove this complexity. Ref: https://lists.gnu.org/r/emacs-devel/2017-09/msg00313.html * doc/misc/cl.texi (Symbols, Creating Symbols, Efficiency Concerns) (Obsolete Setf Customization): Don't document above obsolete function. * lisp/emacs-lisp/cl-macs.el (cl--parse-loop-clause): * lisp/emacs-lisp/edebug.el (edebug-make-form-wrapper): * lisp/obsolete/cl.el (cl--function-convert, lexical-let): * lisp/obsolete/thumbs.el (thumbs-temp-file): * lisp/progmodes/eglot.el (eglot--lambda) (eglot--when-live-buffer, eglot--when-buffer-window) (eglot--collecting-xrefs, eglot--glob-parse): * lisp/progmodes/flymake.el (flymake--run-backend): * test/lisp/emacs-lisp/package-tests.el (with-package-test): * test/lisp/progmodes/eglot-tests.el (eglot--guessing-contact): * test/lisp/progmodes/elisp-mode-tests.el (elisp-shorthand-read-buffer, elisp-shorthand-read-from-string): Prefer plain gensym to cl-gensym in files that can depend on Emacs 26.1. * lisp/jsonrpc.el (jsonrpc-lambda, jsonrpc-request): Prefer gensym to cl-gensym only when defined, as this file supports Emacs 25.1 * test/lisp/emacs-lisp/cl-macs-tests.el (cl-lib-test-gensym): Simplify test as 'should' no longer uses cl-gensym. (cherry picked from commit 60b071e224136207f7fa24983037522e637e7efa) --- diff --git a/doc/misc/cl.texi b/doc/misc/cl.texi index b4c1f29f47f..df67478a5aa 100644 --- a/doc/misc/cl.texi +++ b/doc/misc/cl.texi @@ -2804,7 +2804,7 @@ missing from Emacs Lisp. @menu * Property Lists:: @code{cl-get}, @code{cl-remprop}, @code{cl-getf}, @code{cl-remf}. -* Creating Symbols:: @code{cl-gensym}, @code{cl-gentemp}. +* Creating Symbols:: @code{cl-gentemp}. @end menu @node Property Lists @@ -2892,30 +2892,10 @@ out the property and value cells. @section Creating Symbols @cindex gensym -@noindent -These functions create unique symbols, typically for use as -temporary variables. - -@defun cl-gensym &optional x -This function creates a new, uninterned symbol (using @code{make-symbol}) -with a unique name. (The name of an uninterned symbol is relevant -only if the symbol is printed.) By default, the name is generated -from an increasing sequence of numbers, @samp{G1000}, @samp{G1001}, -@samp{G1002}, etc. If the optional argument @var{x} is a string, that -string is used as a prefix instead of @samp{G}. Uninterned symbols -are used in macro expansions for temporary variables, to ensure that -their names will not conflict with ``real'' variables in the user's -code. - -(Internally, the variable @code{cl--gensym-counter} holds the counter -used to generate names. It is initialized with zero and incremented -after each use.) -@end defun - @defun cl-gentemp &optional x -This function is like @code{cl-gensym}, except that it produces a new -@emph{interned} symbol. If the symbol that is generated already -exists, the function keeps incrementing the counter and trying +This function is like the built-in @code{gensym}, except that it +produces a new @emph{interned} symbol. If the symbol that is generated +already exists, the function keeps incrementing the counter and trying again until a new symbol is generated. @end defun @@ -4419,18 +4399,18 @@ an expansion similar to: @example (cl-block nil (let* ((x 0) - (G1004 nil)) + (g1004 nil)) (while (< x 10) - (setq G1004 (cons x G1004)) + (setq g1004 (cons x g1004)) (setq x (+ x 1))) - (nreverse G1004))) + (nreverse g1004))) @end example @noindent will be inserted into the buffer. (The @code{cl-block} macro is expanded differently in the interpreter and compiler, so @code{cl-prettyexpand} just leaves it alone. The temporary -variable @code{G1004} was created by @code{cl-gensym}.) +variable @code{g1004} was created by @code{gensym}.) If the optional argument @var{full} is true, then @emph{all} macros are expanded, including @code{cl-block}, @code{cl-eval-when}, @@ -5157,7 +5137,7 @@ temporary variables. In the setf-methods generated by @code{defsetf}, the second return value is simply the list of arguments in the place form, and the first return value is a list of a corresponding number of temporary variables generated -by @code{cl-gensym}. +by @code{gensym}. @end defmac @node GNU Free Documentation License diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el index dc67e55f371..a1c34fa01e7 100644 --- a/lisp/emacs-lisp/cl-macs.el +++ b/lisp/emacs-lisp/cl-macs.el @@ -166,6 +166,7 @@ whether X is known at compile time, macroexpand it completely in (defun cl-gensym (&optional prefix) "Generate a new uninterned symbol. The name is made by appending a number to PREFIX, default \"G\"." + (declare (obsolete gensym "31.1")) (let ((pfix (if (stringp prefix) prefix "G")) (num (if (integerp prefix) prefix (prog1 cl--gensym-counter @@ -1277,10 +1278,10 @@ For more details, see Info node `(cl)Loop Facility'. (let ((loop-for-bindings nil) (loop-for-sets nil) (loop-for-steps nil) (ands nil)) (while - ;; Use `cl-gensym' rather than `make-symbol'. It's important that + ;; Use `gensym' rather than `make-symbol'. It's important that ;; (not (eq (symbol-name var1) (symbol-name var2))) because ;; these vars get added to the macro-environment. - (let ((var (or (pop cl--loop-args) (cl-gensym "--cl-var--")))) + (let ((var (or (pop cl--loop-args) (gensym "--cl-var--")))) (setq word (pop cl--loop-args)) (if (eq word 'being) (setq word (pop cl--loop-args))) (if (memq word '(the each)) (setq word (pop cl--loop-args))) diff --git a/lisp/emacs-lisp/edebug.el b/lisp/emacs-lisp/edebug.el index 3033e8378f5..aea7b459736 100644 --- a/lisp/emacs-lisp/edebug.el +++ b/lisp/emacs-lisp/edebug.el @@ -1369,7 +1369,7 @@ infinite loops when the code/environment contains a circular object.") ;; Set the name here if it was not set by edebug-make-enter-wrapper. (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"))) ;; Add this def as a dependent of containing def. Buggy. '(if (and edebug-containing-def-name diff --git a/lisp/jsonrpc.el b/lisp/jsonrpc.el index 669ceba30ef..4b8a6cec921 100644 --- a/lisp/jsonrpc.el +++ b/lisp/jsonrpc.el @@ -204,7 +204,8 @@ JSONRPC message." ;;; (cl-defmacro jsonrpc-lambda (cl-lambda-list &body body) (declare (indent 1) (debug (sexp &rest form))) - (let ((e (cl-gensym "jsonrpc-lambda-elem"))) + (let ((e (funcall (if (fboundp 'gensym) 'gensym 'cl-gensym) + "jsonrpc-lambda-elem"))) `(lambda (,e) (apply (cl-function (lambda ,cl-lambda-list ,@body)) ,e)))) (defun jsonrpc-events-buffer (connection) @@ -405,7 +406,9 @@ remote endpoint (normal or error) are ignored and the function exits returning CANCEL-ON-INPUT-RETVAL. If CANCEL-ON-INPUT is a function, it is invoked with one argument, an integer identifying the canceled request as specified in the JSONRPC 2.0 spec." - (let* ((tag (cl-gensym "jsonrpc-request-catch-tag")) id-and-timer + (let* ((tag (funcall (if (fboundp 'gensym) 'gensym 'cl-gensym) + "jsonrpc-request-catch-tag")) + id-and-timer canceled (throw-on-input nil) (retval diff --git a/lisp/obsolete/cl.el b/lisp/obsolete/cl.el index 5fbfbb7899e..8a7e54a981c 100644 --- a/lisp/obsolete/cl.el +++ b/lisp/obsolete/cl.el @@ -325,7 +325,7 @@ The two cases that are handled are: (cddr f)))) (if (and cl-closure-vars (cl--expr-contains-any body cl-closure-vars)) - (let* ((new (mapcar #'cl-gensym cl-closure-vars)) + (let* ((new (mapcar #'gensym cl-closure-vars)) (sub (cl-pairlis cl-closure-vars new)) (decls nil)) (while (or (stringp (car body)) (eq (car-safe (car body)) 'interactive)) @@ -372,7 +372,7 @@ lexical closures as in Common Lisp. (cons (cons 'function #'cl--function-convert) macroexpand-all-environment)))) (if (not (get (car (last cl-closure-vars)) 'used)) - ;; Turn (let ((foo (cl-gensym))) + ;; Turn (let ((foo (gensym))) ;; (set foo ) ...(symbol-value foo)...) ;; into (let ((foo )) ...(symbol-value 'foo)...). ;; This is good because it's more efficient but it only works with diff --git a/lisp/obsolete/thumbs.el b/lisp/obsolete/thumbs.el index a4f28ce97c5..ac8f9c5fad6 100644 --- a/lisp/obsolete/thumbs.el +++ b/lisp/obsolete/thumbs.el @@ -60,7 +60,7 @@ ;;; Code: (require 'dired) -(require 'cl-lib) ; for cl-gensym +(require 'cl-lib) ;; CUSTOMIZATIONS @@ -176,7 +176,7 @@ this value can let another user see some of your images." (format "%s%s-%s.jpg" (thumbs-temp-dir) thumbs-temp-prefix - (cl-gensym "T"))) + (gensym "T"))) (defun thumbs-thumbsdir () "Return the current thumbnails directory (from `thumbs-thumbsdir'). diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index f812b4c925d..df54c9bbf8e 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -879,7 +879,7 @@ Honor `eglot-strict-mode'." "Function of args CL-LAMBDA-LIST for processing INTERFACE objects. Honor `eglot-strict-mode'." (declare (indent 1) (debug (sexp &rest form))) - (let ((e (cl-gensym "jsonrpc-lambda-elem"))) + (let ((e (gensym "jsonrpc-lambda-elem"))) `(lambda (,e) (cl-block nil (eglot--dbind ,cl-lambda-list ,e ,@body))))) (cl-defmacro eglot--dcase (obj &rest clauses) @@ -925,12 +925,12 @@ treated as in `eglot--dbind'." (cl-defmacro eglot--when-live-buffer (buf &rest body) "Check BUF live, then do BODY in it." (declare (indent 1) (debug t)) - (let ((b (cl-gensym))) + (let ((b (gensym))) `(let ((,b ,buf)) (if (buffer-live-p ,b) (with-current-buffer ,b ,@body))))) (cl-defmacro eglot--when-buffer-window (buf &body body) "Check BUF showing somewhere, then do BODY in it." (declare (indent 1) (debug t)) - (let ((b (cl-gensym))) + (let ((b (gensym))) `(let ((,b ,buf)) ;;notice the exception when testing with `ert' (when (or (get-buffer-window ,b) (ert-running-test)) @@ -3176,7 +3176,7 @@ may be called multiple times (respecting the protocol of (cl-defmacro eglot--collecting-xrefs ((collector) &rest body) "Sort and handle xrefs collected with COLLECTOR in BODY." (declare (indent 1) (debug (sexp &rest form))) - (let ((collected (cl-gensym "collected"))) + (let ((collected (gensym "collected"))) `(unwind-protect (let (,collected) (cl-flet ((,collector (xref) (push xref ,collected))) @@ -4289,7 +4289,7 @@ at point. With prefix argument, prompt for ACTION-KIND." collect (cl-loop for (_token regexp emitter) in grammar thereis (and (re-search-forward (concat "\\=" regexp) nil t) - (list (cl-gensym "state-") emitter (match-string 0))) + (list (gensym "state-") emitter (match-string 0))) finally (error "Glob '%s' invalid at %s" (buffer-string) (point)))))) (cl-defun eglot--glob-fsm (states &key (exit 'eobp) noerror) diff --git a/lisp/progmodes/flymake.el b/lisp/progmodes/flymake.el index fb751085583..150658f4972 100644 --- a/lisp/progmodes/flymake.el +++ b/lisp/progmodes/flymake.el @@ -1444,7 +1444,7 @@ If it is running also stop it." ARGS is a keyword-value plist passed to the backend along with a report function." (flymake-log :debug "Running backend %s" backend) - (let ((run-token (cl-gensym "backend-token"))) + (let ((run-token (gensym "backend-token"))) (flymake--with-backend-state backend state (setf (flymake--state-running state) run-token (flymake--state-disabled state) nil diff --git a/test/lisp/emacs-lisp/cl-macs-tests.el b/test/lisp/emacs-lisp/cl-macs-tests.el index a3118c9b556..64ccdd2d1ce 100644 --- a/test/lisp/emacs-lisp/cl-macs-tests.el +++ b/test/lisp/emacs-lisp/cl-macs-tests.el @@ -961,21 +961,14 @@ See Bug#57915." :b 1))) (ert-deftest cl-lib-test-gensym () - ;; Since the expansion of `should' calls `cl-gensym' and thus has a - ;; side-effect on `cl--gensym-counter', we have to make sure all - ;; macros in our test body are expanded before we rebind - ;; `cl--gensym-counter' and run the body. Otherwise, the test would - ;; fail if run interpreted. - (let ((body (byte-compile - '(lambda () - (should (equal (symbol-name (cl-gensym)) "G0")) - (should (equal (symbol-name (cl-gensym)) "G1")) - (should (equal (symbol-name (cl-gensym)) "G2")) - (should (equal (symbol-name (cl-gensym "foo")) "foo3")) - (should (equal (symbol-name (cl-gensym "bar")) "bar4")) - (should (equal cl--gensym-counter 5)))))) + (with-suppressed-warnings ((obsolete cl-gensym)) (let ((cl--gensym-counter 0)) - (funcall body)))) + (should (equal (symbol-name (cl-gensym)) "G0")) + (should (equal (symbol-name (cl-gensym)) "G1")) + (should (equal (symbol-name (cl-gensym)) "G2")) + (should (equal (symbol-name (cl-gensym "foo")) "foo3")) + (should (equal (symbol-name (cl-gensym "bar")) "bar4")) + (should (equal cl--gensym-counter 5))))) (ert-deftest cl-the () (should (eql (cl-the integer 42) 42)) diff --git a/test/lisp/progmodes/eglot-tests.el b/test/lisp/progmodes/eglot-tests.el index eec076da723..2b6e09a4d16 100644 --- a/test/lisp/progmodes/eglot-tests.el +++ b/test/lisp/progmodes/eglot-tests.el @@ -1236,7 +1236,7 @@ GUESSED-MAJOR-MODES-SYM are bound to the useful return values of `eglot--guess-contact'. Unless the server program evaluates to \"a-missing-executable.exe\", this macro will assume it exists." (declare (indent 1) (debug t)) - (let ((i-sym (cl-gensym))) + (let ((i-sym (gensym))) `(dolist (,i-sym '(nil t)) (let ((,interactive-sym ,i-sym) (buffer-file-name "_") diff --git a/test/lisp/progmodes/elisp-mode-tests.el b/test/lisp/progmodes/elisp-mode-tests.el index c4a2847285b..06edcdba703 100644 --- a/test/lisp/progmodes/elisp-mode-tests.el +++ b/test/lisp/progmodes/elisp-mode-tests.el @@ -1043,7 +1043,7 @@ evaluation of BODY." (ert-deftest elisp-shorthand-read-buffer () - (let* ((gsym (downcase (symbol-name (cl-gensym "sh-")))) + (let* ((gsym (downcase (symbol-name (gensym "sh-")))) (shorthand-sname (format "s-%s" gsym)) (expected (intern (format "shorthand-longhand-%s" gsym)))) (cl-assert (not (intern-soft shorthand-sname))) @@ -1057,7 +1057,7 @@ evaluation of BODY." (should (not (intern-soft shorthand-sname))))) (ert-deftest elisp-shorthand-read-from-string () - (let* ((gsym (downcase (symbol-name (cl-gensym "sh-")))) + (let* ((gsym (downcase (symbol-name (gensym "sh-")))) (shorthand-sname (format "s-%s" gsym)) (expected (intern (format "shorthand-longhand-%s" gsym)))) (cl-assert (not (intern-soft shorthand-sname)))