Macros 无序指定可选参数

Macros 无序指定可选参数,macros,common-lisp,optional-parameters,Macros,Common Lisp,Optional Parameters,下面的代码使用隐式可选参数实现宏调用——隐式,因为它隐藏在&rest参数中。是否有更好的方法对宏(及其支持函数)进行编码——可能是通过使用&optional关键字显式显示可选参数(或者其他方式)?首选第一个参数是必需的,第二个参数是可选的,其余的许多参数都是必需的。如果可能的话,也希望宏定义保持简单,由支持函数完成工作(但也希望学习更高级的方法): 另外需要澄清的一点是:上面的插槽值实际上是各种各样的规范,表示为(有时是深度嵌套的)lisp树。函数install action解释规范并将其语义内

下面的代码使用隐式可选参数实现宏调用——隐式,因为它隐藏在&rest参数中。是否有更好的方法对宏(及其支持函数)进行编码——可能是通过使用&optional关键字显式显示可选参数(或者其他方式)?首选第一个参数是必需的,第二个参数是可选的,其余的许多参数都是必需的。如果可能的话,也希望宏定义保持简单,由支持函数完成工作(但也希望学习更高级的方法):


另外需要澄清的一点是:上面的插槽值实际上是各种各样的规范,表示为(有时是深度嵌套的)lisp树。函数install action解释规范并将其语义内容安装到数据库中。

参数和参数列表:style

有明确的参数列表是很有用的。CommonLisp为它提供了广泛的支持。但即便如此,并非所有参数列表的想法都能得到支持。正如jkiiski在他的评论中所指出的,有一个能说话的参数列表总是很有帮助的:它可以帮助开发人员,编译器可以在编译时捕获一些错误,Lisp可以提供更好的调试信息

样式规则之一:可选参数应位于参数列表的末尾。CommonLisp本身至少在一个地方违反了这一点(现在只能记住一个函数),而且它总是很痛苦且容易出错

修复安装操作的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)
它变得更长,但可读性大大提高

附带问题:我们是否需要一个宏观的行动定义以及原因?

产生这种宏的主要原因通常是:

  • 少引用
  • 特殊语法
  • 编译时副作用
  • 扩展到其他宏调用

如果需要rest参数,最好将其设置为常规命名参数。这样宏的用户就可以从lambda列表中看到他们应该给它什么,而不必猜测(/阅读文档)。可选的持续时间可以是结尾处的关键字/可选参数。或者您可以为宏设置类似于
(名称(&可选(持续时间0))slot1 slot2 slot3)
的内容。如果我能让它工作,我更愿意使用您的解决方案。(不知道required/optional可以像这样混合。)如何让(defmacro定义操作(名称(&可选(持续时间0))slot1 slot2 slot3)`(安装操作',名称',持续时间',slot1',slot2',slot3))正确地进行宏扩展?(ps:如何在Stackoverflow上记录首选解决方案以供评论?)这应该起作用:
(宏扩展(定义操作foo(3)a b c))
=>
(安装操作“foo”3“a”b c)
。请记住,您必须在持续时间周围放置参数(如果没有持续时间,则为空参数)。缺少一个词:“可选参数应位于参数列表的末尾”。为了便于阅读,我希望将可选参数放在lambda列表的第二位。它只是一个数字,插槽参数可能是复杂的树(请参见上面的问题编辑)。担心在编写规范的最后,可选参数可能太容易被忽略。slot:关键字是否是最好的方法,即使它们都是必需的?@davypough:主要问题是,普通Lisp本机不支持平面参数列表中必需参数之前的可选参数。这应该给我们一个提示,这可能不是一个好主意。@davypough:通过关键字参数,您可以检查它们是否确实提供了。然后,您还可以将持续时间放在前面,因为顺序并不重要。
(define-action move :slots (a b c) :duration 1)