From 754bbf7a25a8dda49b5d08ef0d0443bbf5af0e36 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Sun, 7 Apr 2024 13:41:34 -0500 Subject: new repository --- devdocs/elisp/surprising-local-vars.html | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 devdocs/elisp/surprising-local-vars.html (limited to 'devdocs/elisp/surprising-local-vars.html') diff --git a/devdocs/elisp/surprising-local-vars.html b/devdocs/elisp/surprising-local-vars.html new file mode 100644 index 00000000..37947ea1 --- /dev/null +++ b/devdocs/elisp/surprising-local-vars.html @@ -0,0 +1,30 @@ +

Local Variables in Macro Expansions

In the previous section, the definition of for was fixed as follows to make the expansion evaluate the macro arguments the proper number of times:

(defmacro for (var from init to final do &rest body)
+  "Execute a simple for loop: (for i from 1 to 10 do (print i))."
+
+
  `(let ((,var ,init)
+         (max ,final))
+     (while (<= ,var max)
+       ,@body
+       (inc ,var))))
+
+

The new definition of for has a new problem: it introduces a local variable named max which the user does not expect. This causes trouble in examples such as the following:

(let ((max 0))
+  (for x from 0 to 10 do
+    (let ((this (frob x)))
+      (if (< max this)
+          (setq max this)))))
+
+

The references to max inside the body of the for, which are supposed to refer to the user’s binding of max, really access the binding made by for.

The way to correct this is to use an uninterned symbol instead of max (see Creating Symbols). The uninterned symbol can be bound and referred to just like any other symbol, but since it is created by for, we know that it cannot already appear in the user’s program. Since it is not interned, there is no way the user can put it into the program later. It will never appear anywhere except where put by for. Here is a definition of for that works this way:

(defmacro for (var from init to final do &rest body)
+  "Execute a simple for loop: (for i from 1 to 10 do (print i))."
+  (let ((tempvar (make-symbol "max")))
+    `(let ((,var ,init)
+           (,tempvar ,final))
+       (while (<= ,var ,tempvar)
+         ,@body
+         (inc ,var)))))
+
+

This creates an uninterned symbol named max and puts it in the expansion instead of the usual interned symbol max that appears in expressions ordinarily.

+

+ Copyright © 1990-1996, 1998-2022 Free Software Foundation, Inc.
Licensed under the GNU GPL license.
+ https://www.gnu.org/software/emacs/manual/html_node/elisp/Surprising-Local-Vars.html +

+
-- cgit v1.2.3