下面的代码实现了一个带有隐式可选参数的宏调用,因为它隐藏在& rest参数中。有没有更好的方法来编写宏(及其支持函数) - 可能通过使用&可选关键字(或者其他方式)使可选参数显式化?最好是第一个参数是必需的,第二个是可选的,并且需要许多其余的参数。也希望保留宏定义简单,由支撑作用所做的工作,如果可能的话(但想学习更多先进的方法太):按顺序指定可选参数
(defstruct action
name duration slot1 slot2 slot3)
(defmacro define-action (name &rest rest)
`(install-action ',name ',rest))
(defun install-action (name &rest rest)
(let* ((slots (first rest))
(duration (if (numberp (first slots))
(prog1 (first slots)
(setf slots (cdr slots)))
0))
(action (make-action :name name :duration duration
:slot1 (first slots) :slot2 (second slots)
:slot3 (third slots))))
(print action)))
(define-action move a b c) ;first example no duration
(define-action move 1 a b c) ;second example with duration=1
#S(ACTION :NAME MOVE :DURATION 0 :SLOT1 A :SLOT2 B :SLOT3 C)
#S(ACTION :NAME MOVE :DURATION 1 :SLOT1 A :SLOT2 B :SLOT3 C)
澄清的附加点:上面的槽值是真的不同规范表示为(有时深度嵌套)lisp树。函数install-action解释规范并将其语义内容安装到数据库中。
如果其他参数是必需的,最好使它们成为常规的命名参数。这样,宏的用户可以从lambda列表中看到他们应该给它的内容,而不必猜测(/阅读文档)。可选的持续时间可以是最后的关键字/可选参数。或者你可以为宏指定'(name(&optional(duration 0))slot1 slot2 slot3)'。 – jkiiski
如果我能使用它,我宁愿使用您的解决方案。 (不知道必填项/可选项可能会混在一起)你如何得到 (defmacro define-action(name(&optional(duration 0))slot1 slot2 slot3) '(install-action',name',duration ',slot1',slot2',slot3)) to macroexpand properly? (ps:如何在Stackoverflow上记录注释的首选解决方案?) – davypough
这应该起作用:'(macroexpand'(define-action foo(3)abc))'=>'(INSTALL-ACTION'FOO'3' A'B'C)'。请记住,您必须将持续时间放在身边(如果您没有持续时间,则必须将空闲的身体放置)。 – jkiiski