就像其他答案说的那样,这只是defvar的工作方式,但是您可以绕开它,毕竟这是elisp。
您可以临时重新定义defvar的工作方式,并在此期间重新加载要重置的软件包。
我写了一个宏,其中在评估身体时,将始终重新评估defvars值。
(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)))))
用法示例:
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))
注意:这仅应用于重新评估defvar,因为重新评估时它仅忽略文档字符串。您可以修改宏以支持重新评估也适用于文档字符串,但是我将由您自己决定。
在你的情况下你可以做
(with-forced-defvar-eval (require 'some-package))
但是知道那些编写elisp的人这样做是希望defvar能够按指定方式工作,这可能是因为他们使用defvar来定义,并在某个init函数中使用setq来指定值,所以您可能最终会放弃不想要的变量,但是这可能很少见。
替代实施
使用此方法,您可以全局重新定义defvar,并控制是否通过更改新defvar-always-reeval-values
符号的值来定义符号的值是否设置为INIT-VALUE arg 。
;; 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
,然后重新评估缓冲区中的代码。