(defmacro ek/bind-evil-keys-map (state keymap key-fn-list)
  (let* ((key-fns (symbol-value key-fn-list))
       (body (mapcar
              (lambda (pair)
                `(evil-define-key ,state ,keymap (kbd ,(car pair)) ,(cdr pair)))
  `(progn ,@body))

(defvar motion-keys
    ("C-o" . 'ek/xref-go-back)
    ("<C-i>" . 'ek/xref-go-forward)

(ek/bind-evil-keys-map '(normal motion) 'global motion-keys)

Here I'm using symbol-value,
I read macro doesn't evaluate arguments (but function does) so, I tried (eval key-fn-list).

But it seems it is not same as (symbol-value key-fn-list).
So what is the difference?

  • 1
    FWIW, you should not eval / symbol-value a symbol coming from a macro form during macro-expansion. (Actually you can, but you may get unexpected results.)
    – shynur
    Commented Sep 1, 2023 at 8:38

2 Answers 2


If you need to evaluate the arguments, then you shouldn’t be writing a macro. Just write this as an ordinary function.

To answer your question, simply use C-h f to look up the help for both eval and symbol-value. You will soon see the difference; eval evaluates arbitrary code, while symbol-value takes a symbol and returns the value of the variable named by that symbol.


I checked the documentation of evil-define-key (I don’t use evil-mode myself), and I have no idea why you are writing this macro. evil-define-key already lets you bind an arbitrary number of keys. Your code could just be written like this:

(evil-define-key '(normal insert) global-map
    "C-o"   'ek/xref-go-back
    "<C-i>" 'ek/xref-go-forward)

You really should read the documentation of these things using C-h i. It will save you a lot of wasted work.

  • I read function evaluates the argument (whereas macro doesnt) , here evaluate is not the same as eval ? is it actually symbol-value ?
    – eugene
    Commented Sep 1, 2023 at 6:01
  • I tried to not use macro so hard (because it was so hard to use it for the first time) but I couldn't make a function that can take a symbol and forward it to a macro here (evil-define-key is the macro)
    – eugene
    Commented Sep 1, 2023 at 6:05
  • 1
    “Evaluate” always means eval. If eval sees a symbol, it will call symbol-value. If it sees (+ 2 2), it will call (apply #'+ 2 2), and so on.
    – db48x
    Commented Sep 1, 2023 at 12:09

(Here I don't discuss the reasonableness of OP evaluating a symbol from a macro form during macro-expansion.
 You have your own idea, either way, I can't stop you from doing it.)

You should always use symbol-value when possible.
GNU Emacs Lisp Reference Manual, 10.5 Eval:

Often eval is not needed and something else should be used instead. For example, to get the value of a variable, while eval works, symbol-value is preferable;

Avoid using eval when possible.
See also “A mutable object stops being mutable if it is part of an expression that is evaluated.”.
GNU Emacs Lisp Reference Manual, 2.9 Mutability:

A mutable object stops being mutable if it is part of an expression that is evaluated. For example:

(let* ((x (list 0.5))
       (y (eval (list 'quote x))))
  (setcar x 1.5) ;; The program should not do this.

Although the list (0.5) was mutable when it was created, it should not have been changed via setcar because it was given to eval.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.