Misalkan saya memiliki file bernama elisp-defvar-test.el
mengandung:
;;; 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
Saya memuat file ini dan kemudian pergi ke buffer awal dan menjalankan:
(setq lexical-binding t)
(f1 5)
(let ((my-dynamic-var 5))
(f2))
(f1 5)
mengembalikan 5 seperti yang diharapkan, menunjukkan bahwa tubuh f1
memperlakukan my-dynamic-var
sebagai variabel cakupan dinamis, seperti yang diharapkan. Namun, formulir terakhir memberikan kesalahan variabel void my-dynamic-var
, yang menunjukkan bahwa ia menggunakan pelingkupan leksikal untuk variabel ini. Ini sepertinya bertentangan dengan dokumentasi untuk defvar
, yang mengatakan:
The
defvar
bentuk juga menyatakan variabel sebagai "khusus", sehingga selalu dinamis terikat bahkan jikalexical-binding
adalah t.
Jika saya mengubah defvar
formulir dalam file pengujian untuk memberikan nilai awal, maka variabel selalu diperlakukan sebagai dinamis, seperti yang dikatakan dokumentasi. Adakah yang bisa menjelaskan mengapa pelingkupan suatu variabel ditentukan oleh apakah defvar
diberi nilai awal atau tidak saat mendeklarasikan variabel itu?
Inilah backtrace kesalahan, jika itu penting:
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)