Используйте строковую переменную в качестве аргумента макроса

Я хочу этот код:

(setq name "foobar")
(defun (intern name) ())

сделать то же самое, что и:

(defun foobar ())

Я пробовал это (из этого вопроса):

(defmacro make-my-function (name)
(list 'defun
(intern (format "my-%s-function" name)) ()
    (list 'interactive)
    '(message "It's work !")))

Но я получаю функцию my-name-function, но мне нужна my-foobar-function. Моя цель - определить второстепенные режимы из списка клавиш.

Спасибо

2 ответа

Ваш макрос работает нормально. Как вы пытались вызвать его? Вы должны вызывать так: (make-my-function foo), затем M-: (symbol-function 'my-foo-function) показывает определение функции:

(lambda nil
  (interactive)
  (message "It's work !"))

Причина, по которой ваша первоначальная попытка до определения макроса не сработала, заключается в том, что defun является макросом - он не оценивает свои аргументы. Так (defun (intern name) ()) синтаксически неверно: defun нужен символ в качестве первого аргумента, и (intern name) это список, а не символ.


Обновлено, после вашего комментария -

Ваш вопрос совершенно неясен. Теперь звучит так, как будто вы хотите позвонить (make-my-function foo) в контексте, где у вас есть переменная my-foo-function, чье значение является строкой.

Если это так, то используйте это:

(defmacro make-my-function (name)
  (list 'defun
        (intern (symbol-value (intern (format "my-%s-function" name))))
        ()
        (list 'interactive)
        '(message "It's work !")))

(setq my-foo-function "toto")
(make-my-function foo)

Я не могу представить такой вариант использования, но подозреваю, что это тоже не то, что вы пытаетесь сделать. Похоже, вы не указали хорошо, что такое требуемое поведение.

Я не могу воссоздать вашу проблему с вашим make-my-function макрос, но попробуйте с обратной цитатой:

(defmacro make-my-function (name)
  `(defun ,(intern (format "my-%s-function" name)) ()
    'interactive
    '(message "It works!")))
Другие вопросы по тегам