Giống như các câu trả lời khác nói, đây chỉ là cách defvar hoạt động, nhưng bạn có thể vượt qua nó, đây là điều tất yếu.
Bạn có thể tạm thời xác định lại cách thức hoạt động của defvar nếu bạn muốn và trong thời gian đó, tải lại các gói bạn muốn đặt lại.
Tôi đã viết một macro trong đó trong quá trình đánh giá cơ thể, các giá trị của defvars sẽ luôn được đánh giá lại.
(defmacro my-fake-defvar (name value &rest _)
"defvar impersonator that forces reeval."
`(progn (setq ,name ,value)
',name))
(defmacro with-forced-defvar-eval (&rest body)
"While evaluating, any defvars encountered are reevaluated"
(declare (indent defun))
(let ((dv-sym (make-symbol "old-defvar")))
`(let ((,dv-sym (symbol-function 'defvar)))
(unwind-protect
(progn
(fset 'defvar (symbol-function 'my-fake-defvar))
,@body)
(fset 'defvar ,dv-sym)))))
Cách sử dụng ví dụ:
file_a.el
(defvar my-var 10)
file_b.el
(with-forced-defvar-eval
(load-file "file_a.el")
(assert (= my-var 10))
(setq my-var 11)
(assert (= my-var 11)
(load-file "file_a.el")
(assert (= my-var 10))
Lưu ý: Điều này chỉ nên được sử dụng cho mục đích đánh giá lại các defvars, vì nó chỉ bỏ qua các tài liệu khi đánh giá lại. Bạn có thể sửa đổi macro để hỗ trợ đánh giá lại cũng áp dụng các tài liệu, nhưng tôi sẽ để nó tùy thuộc vào bạn.
Trong trường hợp của bạn, bạn có thể làm
(with-forced-defvar-eval (require 'some-package))
Nhưng hãy biết những người viết elisp làm gì để mong đợi defvar hoạt động như được chỉ định, có thể họ sử dụng defvar để định nghĩa và setq trong một số hàm init để chỉ định giá trị, vì vậy bạn có thể kết thúc các biến bạn không có ý định nhưng điều này có lẽ là hiếm
Thực hiện thay thế
Sử dụng điều này, bạn có thể xác định lại defvar trên toàn cầu và kiểm soát xem nó có đặt giá trị của biểu tượng thành đối số INIT-VALUE ngay cả khi biểu tượng được xác định bằng cách thay đổi giá trị của defvar-always-reeval-values
biểu tượng mới hay không .
;; save the original defvar definition
(fset 'original-defvar (symbol-function 'defvar))
(defvar defvar-always-reeval-values nil
"When non-nil, defvar will reevaluate the init-val arg even if the symbol is defined.")
(defmacro my-new-defvar (name &optional init-value docstring)
"Like defvar, but when `defvar-always-reeval-values' is non-nil, it will set the symbol's value to INIT-VALUE even if the symbol is defined."
`(progn
(when defvar-always-reeval-values (makunbound ',name))
(original-defvar ,name ,init-value ,docstring)))
;; globally redefine defvar to the new form
(fset 'defvar (symbol-function 'my-new-defvar))
makunbound
và sau đó đánh giá lại mã trong bộ đệm.