Suponha que eu tenha um arquivo chamado elisp-defvar-test.el
contendo:
;;; 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
Carrego esse arquivo e, em seguida, vou para o buffer temporário e execute:
(setq lexical-binding t)
(f1 5)
(let ((my-dynamic-var 5))
(f2))
(f1 5)
retorna 5 conforme o esperado, indicando que o corpo de f1
está tratando my-dynamic-var
como uma variável com escopo dinâmico, conforme o esperado. No entanto, a última forma fornece um erro de variável nula para my-dynamic-var
, indicando que está usando o escopo lexical para essa variável. Isso parece estar em desacordo com a documentação de defvar
, que diz:
O
defvar
formulário também declara a variável como "especial", para que ela seja sempre vinculada dinamicamente, mesmo quelexical-binding
seja t.
Se eu alterar o defvar
formulário no arquivo de teste para fornecer um valor inicial, a variável será sempre tratada como dinâmica, como diz a documentação. Alguém pode explicar por que o escopo de uma variável é determinado pelo fato de ter ou não defvar
sido fornecido um valor inicial ao declarar essa variável?
Aqui está o erro de rastreamento, caso isso importe:
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)