0

I would like to add an alternative answer to the thread How do I force re-evaluation of a defvar? Before doing so, however, I would like to learn how to eliminate the single-quote to prevent evaluation of the argument INPUT to the new function defvar-reevaluate. Perhaps I need a macro instead of a function ....?

BEFORE:

(defun defvar-reevaluate (input)
"Force revelaution of a defvar."
  (let* ((string (prin1-to-string input))
         (form (read string))
         (form (elisp--eval-defun-1 (macroexpand form))))
    (eval form)))

(defvar-reevaluate
  '(defvar undo-auto--this-command-amalgamating "hello-world"
  "My new doc-string"))

AFTER -- without the single quote.

(defvar-reevaluate
  (defvar undo-auto--this-command-amalgamating "hello-world"
  "My new doc-string"))
lawlist
  • 18,826
  • 5
  • 37
  • 118

1 Answers1

1

If you want to pass a non-evaluated expression as argument without quote you have to use a macro since the arguments of (non-special) functions are evaluated before the function call.

(quote a) evaluates just to the un-evaluated expression expr. That's why (quote expr) works as argument.

Your code with the defun replaced by defmacro could look like the following demo.

(defmacro defvar-reevaluate (input)
  "Force revelaution of a defvar."
  (let* ((string (prin1-to-string input))
     (form (read string))
     (form (eval-sexp-add-defvars (elisp--eval-defun-1 (macroexpand form)))))
    form))

(defvar-reevaluate
  (defvar undo-auto--this-command-amalgamating "hello-world"
    "My new doc-string"))

Note that the last eval from your defun is not required since the returned expression of the macro is evaluated at the call of defvar-reevaluate.

Tobias
  • 32,569
  • 1
  • 34
  • 75