Supposons que j'ai un fichier nommé elisp-defvar-test.elcontenant:
;;; 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 f1est traité my-dynamic-varcomme 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
defvarformulaire déclare également la variable comme "spéciale", de sorte qu'elle est toujours liée dynamiquement même silexical-bindingest t.
Si je modifie le defvarformulaire 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 defvarreç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)