Like the other answers say, this is just the way defvar works, but you can get around it, this is elisp after all.
You can temporarily redefine how defvar works if you'd like and during that time, reload the packages you'd like to reset.
I wrote a macro where during the evaluation of the body, defvars values will always be reevaluated.
(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)))))
Example Usage:
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))
Note: This this should only be used for the purpose of reevaluating defvars, as it just ignores docstrings when reevaluating. You can modify the macro to support re-evaluating that applies docstrings as well, but I will leave that up to you.
In your case you could do
(with-forced-defvar-eval (require 'some-package))
But know what those who write elisp do so expecting defvar to work as specified, it could be they use defvar to define and setq in some init function to specify the value, so you may end up nil'ing variables you don't intend but this is probably rare.
Alternative Implementation
Using this you can just redefine defvar globally and control whether or not it will set the symbol's value to the INIT-VALUE arg even if the symbol is defined by changing the value of the new defvar-always-reeval-values
symbol.
;; 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 (condition-case nil
(makunbound ',name)
(error nil)))
(original-defvar ,name ,init-value ,docstring)))
;; globally redefine defvar to the new form
(fset 'defvar (symbol-function 'my-new-defvar))
makunbound
and then re-evaluate the code in the buffer.(incf emacs-major-version)
I can live with happening repeatedly. I'm interested in hacking on code with lots ofdefvar
forms.