Supongamos que tengo un archivo llamado que elisp-defvar-test.elcontiene:
;;; 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
Cargo este archivo y luego entro en el búfer de memoria virtual y ejecuto:
(setq lexical-binding t)
(f1 5)
(let ((my-dynamic-var 5))
(f2))
(f1 5)devuelve 5 como se esperaba, lo que indica que el cuerpo de f1se trata my-dynamic-varcomo una variable de ámbito dinámico, como se esperaba. Sin embargo, la última forma da un error de variable nula para my-dynamic-var, lo que indica que está utilizando el alcance léxico para esta variable. Esto parece estar en desacuerdo con la documentación para defvar, que dice:
El
defvarformulario también declara la variable como "especial", de modo que siempre está unida dinámicamente incluso silexical-bindinges t.
Si cambio el defvarformulario en el archivo de prueba para proporcionar un valor inicial, entonces la variable siempre se trata como dinámica, como dice la documentación. ¿Alguien puede explicar por qué el alcance de una variable está determinado por si se defvarle proporcionó o no un valor inicial al declarar esa variable?
Aquí está el error de seguimiento, en caso de que sea 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)