Supongamos que tengo un archivo llamado que elisp-defvar-test.el
contiene:
;;; 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 f1
se trata my-dynamic-var
como 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
defvar
formulario también declara la variable como "especial", de modo que siempre está unida dinámicamente incluso silexical-binding
es t.
Si cambio el defvar
formulario 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 defvar
le 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)