Search code examples
emacsapplyelispelisp-macro

Elisp use apply on progn for list of functions


I am a new emacs user. And trying to write some Elisp to learn this software better. While I meet some problems.

I want to use apply on progn to run a list of functions in sequence. But I got errors as below. I am just confused and need some help to tell me how to achieve this in Elisp, thanks.

(progn
  (+ 1 1)
  (+ 2 2)
  )
;; => 4

(apply #'progn ((+ 1 1) (+ 2 2)))
;; => Invalid function: (+ 1 1)

(apply #'progn ('(+ 1 1) '(+ 2 2)))
;; => Invalid function: '(+ 1 1)

(apply #'progn '((+ 1 1) (+ 2 2)))
;; => Invalid function: #<subr progn>

I toy play as above cause I come to emacs from vim. So I installed evil and evil number. And want back the vim number inc and dec bindings C-a, C-x. So I write a macro as blow to avoid boilerplate.

(defmacro set-evil-number-keymap (key-set func &rest modes)
  `(apply 'progn
         ,(-map
          (lambda (mode)
            `(define-key ,(intern (concat "evil-" mode "-state-map")) (kbd ,key-set)
              ',(intern
                 (concat "evil-numbers/" func))))
          ,modes)))

(set-evil-number-keymap "C-a" "inc-at-pt" "normal" "insert")
(set-evil-number-keymap "C-x" "dec-at-pt" "normal" "insert")

My expectation is something below. While it just not run.


(progn 
(define-key evil-normal-state-map (kbd "C-a") ’evil-numbers/inc-at-pt) (define-key evil-visual-state-map (kbd "C-a") ’evil-numbers/inc-at-pt))

(progn 
(define-key evil-normal-state-map (kbd "C-x") ’evil-numbers/dec-at-pt) (define-key evil-visual-state-map (kbd "C-x") ’evil-numbers/dec-at-pt))



Solution

  • You don't need to use apply in the macro, elisp have ,@ to flatten a list to args. So the correct answer is

    (defmacro set-evil-number-keymap (key-set func &rest modes)
      `(progn
              ,@(-map
                 (lambda (mode)
                   `(define-key ,(intern (concat "evil-" mode "-state-map")) (kbd ,key-set)
                      ',(intern
                         (concat "evil-numbers/" func))))
                 ,modes)))