Предположим, у меня есть файл с именем elisp-defvar-test.el
:
;;; elisp-defvar-test.el --- -*- lexical-binding: t -*-
(defvar my-dynamic-var)
(defun f1 (x)
"Should return X."
(let ((my-dynamic-var x))
(f2)))
(defun f2 ()
"Returns the current value of `my-dynamic-var'."
my-dynamic-var)
(provide 'elisp-dynamic-test)
;;; elisp-defvar-test.el ends here
Я загружаю этот файл, затем захожу в рабочий буфер и запускаю:
(setq lexical-binding t)
(f1 5)
(let ((my-dynamic-var 5))
(f2))
(f1 5)
возвращает 5, как и ожидалось, указывая, что тело f1
обрабатывается my-dynamic-var
как переменная с динамической областью, как и ожидалось. Тем не менее, последняя форма выдает ошибку void-variable my-dynamic-var
, указывая на то, что она использует лексическую область видимости для этой переменной. Это, кажется, расходится с документацией defvar
, которая гласит:
defvar
Форма также объявляет переменную как «специальный», так что она всегда динамически связана , даже еслиlexical-binding
это т.
Если я изменю defvar
форму в тестовом файле, чтобы указать начальное значение, то переменная всегда обрабатывается как динамическая, как сказано в документации. Кто-нибудь может объяснить, почему область видимости переменной определяется тем, было ли defvar
задано начальное значение при объявлении этой переменной?
Вот обратная трассировка ошибки, если она имеет значение:
Debugger entered--Lisp error: (void-variable my-dynamic-var)
f2()
(let ((my-dynamic-var 5)) (f2))
(progn (let ((my-dynamic-var 5)) (f2)))
eval((progn (let ((my-dynamic-var 5)) (f2))) t)
elisp--eval-last-sexp(t)
eval-last-sexp(t)
eval-print-last-sexp(nil)
funcall-interactively(eval-print-last-sexp nil)
call-interactively(eval-print-last-sexp nil nil)
command-execute(eval-print-last-sexp)