(Другие ответили на ваши прямые вопросы Тион. Но это может ответить на вопрос, стоящий за вашим вопросом, и поговорить с тем, что вы действительно пытаетесь сделать. Если нет, смотрите другие ответы.)
Вы сделать не нужен макрос вообще, чтобы делать то, что вы хотите. Просто используйте defalias
или fset
. Каждый из них является функцией .
(defun foo (cmd &optional search)
(let ((fn (intern (concat "fn-" cmd))))
(defalias fn `(lambda (&optional args)
(let ((str (symbol-name ',fn))
,@(when search
'((dir "~"))))
(message "Called %S from %S" str
(or (and (bound-and-true-p 'dir) dir)
default-directory)))))))
(dolist (x '("f1" "f2")) (foo x))
Затем (symbol-function 'fn-f1)
возвращается:
(lambda (&optional args)
(let ((str (symbol-name 'fn-f1)))
(message "Called %S from %S" str (or (and (bound-and-true-p dir) dir)
default-directory))))
И если вы используете лексического связывания (т.е., поместите привязку локальной переменной -*- lexical-binding: t -*-
в верхнюю часть файла, где этот код определен, тогда вам не нужен какой-либо обратный отсчет. Например:
(defun foo (cmd &optional search)
(let ((fn (intern (concat "fn-" cmd))))
(defalias fn (lambda (&optional args)
(let ((str (symbol-name fn))
(dir (if search "~" default-directory)))
(message "Called %S from %S" str dir))))))
(dolist (x '("f1" "f2")) (foo x))
Если вы сделаете это, то каждая функция fn-f1
и fn-f2
определяется как замыкание, которое выглядит следующим образом:
(symbol-function 'fn-f1)
(closure
((fn . fn-f1)
(search)
(cmd . "f1")
t)
(&optional args)
(let ((str (symbol-name fn))
(dir (if search "~" default-directory)))
(message "Called %S from %S" str dir)))
И (foo "f3" :SEARCH)
определяет функцию fn-f3
(замыкание), который инкапсулирует связывание в противном случае свободной переменной search
с величиной nil
:SEARCH
, так что локальная переменная dir
связывается с "~"
:
(symbol-function 'fn-f3)
(closure
((fn . fn-f3)
(search . :SEARCH) ;; <==============
(cmd . "f3")
t)
(&optional args)
(let ((str (symbol-name fn))
(dir (if search "~" default-directory)))
(message "Called %S from %S" str dir)))