0

This works when I remove the loop but with the loop it does not work.

(defmacro my/def-key (state map)
  (let ((x '(
              (kbd "<leader>z z") (lambda nil (interactive)(message "zz"))
              (kbd "<leader>z f") (lambda nil (interactive)(message "zf")) 
              )))
    ;; works
    ;;`(evil-define-key ,state ,map ,(pop x) ,(pop x))

    ;; Don't work
    (while x 
      `(evil-define-key ,state ,map ,(pop x) ,(pop x)))))

(my/def-key 'normal global-map )
Drew
  • 75,699
  • 9
  • 109
  • 225
ritchie
  • 151
  • 6

1 Answers1

0

A macro has to build and return code, it doesn’t execute anything directly. Your body of your while loop does indeed build some code, but the while itself throws that code away and returns nil. Thus your macro “expands” to nothing at all. You can use macroexpand and macroexpand-1 to debug this sort of thing; evaluating (macroexpand-1 (my/def-key 'normal ,global-map))` would reveal the problem.

I recommend using mapcar or cl-map to walk over the list and accumulate the results in a new list that you can return.

Like this:

(defmacro my/def-key (state map)
  (let* ((definitions '(((kbd "<leader>z z") (lambda nil (interactive) (message "zz")))
                        ((kbd "<leader>z f") (lambda nil (interactive) (message "zf")))))
         (body (mapcar
                (lambda (def)
                  `(evil-define-key ,state ,map ,(car def) ,(cadr def)))
                definitions)))
    `(progn ,@body)))
db48x
  • 15,741
  • 1
  • 19
  • 23
  • Thanks well explained, however not sure how to go about it. I tried this, almost close: `(cl-mapcar (lambda (_)(interactive) (evil-define-key ,state ,map ,(pop x) ,(pop x))) x )` Evil function has a backtick. – ritchie Mar 26 '23 at 01:08
  • Thanks for your help I think I figured it out. – ritchie Mar 26 '23 at 04:15