Giả sử tôi có một tệp có tên elisp-defvar-test.el
:
;;; 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
Tôi tải tập tin này và sau đó đi vào bộ đệm đầu và chạy:
(setq lexical-binding t)
(f1 5)
(let ((my-dynamic-var 5))
(f2))
(f1 5)
trả về 5 như mong đợi, chỉ ra rằng cơ thể f1
đang được coi my-dynamic-var
là một biến có phạm vi động, như mong đợi. Tuy nhiên, biểu mẫu cuối cùng đưa ra lỗi biến void cho my-dynamic-var
, cho biết rằng nó đang sử dụng phạm vi từ vựng cho biến này. Điều này có vẻ mâu thuẫn với tài liệu cho defvar
, trong đó nói:
Biểu
defvar
mẫu cũng khai báo biến là "đặc biệt", để nó luôn bị ràng buộc động ngay cả khilexical-binding
là t.
Nếu tôi thay đổi defvar
biểu mẫu trong tệp thử nghiệm để cung cấp giá trị ban đầu, thì biến luôn được coi là động, như tài liệu nói. Bất cứ ai cũng có thể giải thích tại sao phạm vi của một biến được xác định bởi việc có defvar
được cung cấp giá trị ban đầu hay không khi khai báo biến đó?
Đây là lỗi quay lại, trong trường hợp có vấn đề:
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)