下面的代码使用隐式可选参数实现宏调用 - 隐式,因为它隐藏在& rest参数中。是否有更好的方法来编写宏(及其支持函数) - 可能通过使用& optional关键字(或者可能是其他方式)显式选择可选参数?优选的是,第一参数是必需的,第二参数是必需的,并且需要许多剩余的参数。如果可能的话,还希望保持宏定义简单,支持函数完成工作(但也希望学习更高级的方法):
(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解释规范并将其语义内容安装到数据库中。
答案 0 :(得分:3)
参数和参数列表:样式
有明确的参数列表很有用。 Common Lisp为它提供了广泛的支持。但即使这样,也不能支持每个参数列表的想法。正如jkiiski在他的评论中指出的那样,有一个语音参数列表总是有帮助的:它有助于开发人员,编译器可以在编译时捕获一些错误,Lisp可以提供更好的调试信息。
其中一个样式规则:可选参数应位于参数列表的末尾。 Common Lisp本身至少违反了这一个地方(现在只能记住一个函数)并且它总是很痛苦且容易出错。
修复INSTALL-ACTION的arglist :
(defun install-action (name slots &optional (duration 0))
...)
也修复了宏的arglist
使用它像:
(define-action move (a b c) 1)
最好在宏界面中对事物列表进行分组。
(defmacro define-action (name slots &optional duration)
...)
甚至可以使用名为arguments的关键字:
(define-action move :slots (a b c) :duration 1)
它变得更长,但可读性大大提高。
附带问题:我们需要一个宏DEFINE-ACTION以及为什么?
这种宏的主要原因通常是: