Supposons que j'ai un fichier nommé elisp-defvar-test.el
contenant:
;;; 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
Je charge ce fichier, puis je vais dans le tampon de travail et je lance:
(setq lexical-binding t)
(f1 5)
(let ((my-dynamic-var 5))
(f2))
(f1 5)
renvoie 5 comme prévu, indiquant que le corps de f1
est traité my-dynamic-var
comme une variable de portée dynamique, comme prévu. Cependant, le dernier formulaire donne une erreur de variable nulle pour my-dynamic-var
, indiquant qu'il utilise la portée lexicale pour cette variable. Cela semble en contradiction avec la documentation de defvar
, qui dit:
Le
defvar
formulaire déclare également la variable comme "spéciale", de sorte qu'elle est toujours liée dynamiquement même silexical-binding
est t.
Si je modifie le defvar
formulaire dans le fichier de test pour fournir une valeur initiale, la variable est toujours traitée comme dynamique, comme le dit la documentation. Quelqu'un peut-il expliquer pourquoi la portée d'une variable est déterminée par le fait d'avoir defvar
reçu ou non une valeur initiale lors de la déclaration de cette variable?
Voici la trace d'erreur, au cas où cela serait important:
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)