Spec-Zone.ru › Elisp

Локальные переменные в макрорасширениях

В предыдущем разделе определение for было исправлено следующим образом, чтобы расширение оценивало аргументы макроса нужное количество раз:

(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))))

В новом определении for возникла новая проблема: оно вводит локальную переменную с именем max, которой пользователь не ожидает. Это вызывает трудности в таких примерах, как следующий:

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

Ссылки на max внутри тела for, которые должны ссылаться на привязку пользователя max, на самом деле обращаются к привязке, сделанной for.

Способом исправить это является использование неинтернированного символа вместо max (см. Создание символов). Неинтернированный символ можно привязать и использовать как любой другой символ, но так как он создан for, мы знаем, что он не может уже присутствовать в программе пользователя. Поскольку он не интернирован, пользователь не может поместить его в программу позже. Он никогда не появится нигде, кроме как помещенный for . Вот определение for, которое работает таким образом:

(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)))))

Это создает неинтернированный символ с именем max и помещает его в расширение вместо обычного интернированного символа max, который обычно появляется в выражениях.

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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API