สมมติว่าฉันมีชื่อไฟล์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
ฉันโหลดไฟล์นี้แล้วไปที่บัฟเฟอร์รอยขีดข่วนและเรียกใช้:
(setq lexical-binding t)
(f1 5)
(let ((my-dynamic-var 5))
(f2))
(f1 5)
ส่งคืน 5 ตามที่คาดไว้ซึ่งแสดงว่าเนื้อความของf1
ถือmy-dynamic-var
เป็นตัวแปรที่กำหนดขอบเขตแบบไดนามิกตามที่คาดไว้ อย่างไรก็ตามรูปแบบสุดท้ายให้ข้อผิดพลาดเป็นโมฆะตัวแปรเพื่อmy-dynamic-var
ระบุว่ามันกำลังใช้การกำหนดขอบเขตศัพท์สำหรับตัวแปรนี้ ดูเหมือนว่าจะขัดแย้งกับเอกสารสำหรับdefvar
ซึ่งบอกว่า:
defvar
รูปแบบนอกจากนี้ยังประกาศตัวแปรเป็น "พิเศษ" เพื่อที่จะอยู่เสมอผูกพันแบบไดนามิกแม้ว่าlexical-binding
เป็นเสื้อ
ถ้าฉันเปลี่ยนdefvar
รูปแบบในไฟล์ทดสอบเพื่อระบุค่าเริ่มต้นตัวแปรนั้นจะถือว่าเป็นแบบไดนามิกเสมอเช่นเอกสารกล่าว ทุกคนสามารถอธิบายได้หรือไม่ว่าทำไมการกำหนดขอบเขตของตัวแปรถูกกำหนดโดยdefvar
ค่าเริ่มต้นเมื่อมีการประกาศตัวแปรนั้นหรือไม่
นี่คือข้อผิดพลาดย้อนหลังในกรณีที่สำคัญ:
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)