1

I have the following macro

(defmacro test-macro (arg)
  `(defun (intern (concat "test-func-called" ,arg)) ()
     (message "I do nothing")))

When I call to this macro

(test-macro "test")

It gives me the following error

Wrong type argument: symbolp, (intern (concat "test-func-called" "test"))

Evaluating the following gives me t

(symbolp (intern (concat "test-func-called" "test")))
  • 1
    You need to unquote the intern. Put a comma before its opening parenthesis. – Dan Jun 19 '16 at 19:47
5

The way you test macros is with macroexpand:

(macroexpand-1 '(test-macro "test"))
==> (defun (intern (concat "test-func-called" "test")) nil (message "I do nothing"))

This makes the error obvious: the function intern should be called at macroexpansion time, not at evaluation time (since defun does not evaluate its first argument).

Thus, the fix is:

(defmacro test-macro (arg)
  `(defun ,(intern (concat "test-func-called" arg)) ()
     (message "I do nothing")))
(macroexpand-1 '(test-macro "test"))
==> (defun test-func-calledtest nil (message "I do nothing"))
  • Or use macroexpand if before Emacs 25, where macroexpand-1 is introduced. That returns (defalias (quote (intern (concat "test-func-called" "test"))) (function (lambda nil (message "I do nothing")))), which indicates the same problem, but expressed in terms of defalias, not defun. – Drew Jun 19 '16 at 23:50
  • Thanks! On a separate note, is that a good way to define a macro that defines a function? Basically I want to define 5-6 interactive functions by writing one macro and then call it to create functions for me. – Russ Kiselev Jun 20 '16 at 4:54
  • @RussKiselev: yes, this is the way to go; try macroexpanding defstruct forms. – sds Jun 20 '16 at 12:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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