Supponiamo di avere un file chiamato elisp-defvar-test.el
contenente:
;;; 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
Carico questo file e poi vado nel buffer di memoria ed eseguo:
(setq lexical-binding t)
(f1 5)
(let ((my-dynamic-var 5))
(f2))
(f1 5)
restituisce 5 come previsto, indicando che il corpo di f1
sta trattando my-dynamic-var
come una variabile con ambito dinamico, come previsto. Tuttavia, l'ultimo modulo fornisce un errore variabile vuoto per my-dynamic-var
, indicando che sta usando l'ambito lessicale per questa variabile. Questo sembra in contrasto con la documentazione per defvar
, che dice:
Il
defvar
modulo dichiara inoltre la variabile come "speciale", in modo che sia sempre legata dinamicamente anche selexical-binding
è t.
Se cambio il defvar
modulo nel file di test per fornire un valore iniziale, la variabile viene sempre trattata come dinamica, come dice la documentazione. Qualcuno può spiegare perché l'ambito di una variabile è determinato dal fatto che sia defvar
stato fornito o meno un valore iniziale durante la dichiarazione di quella variabile?
Ecco l'errore backtrace, nel caso in cui sia importante:
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)