不按顺序指定可选参数

时间:2016-11-14 03:28:04

标签: macros common-lisp optional-parameters

下面的代码使用隐式可选参数实现宏调用 - 隐式,因为它隐藏在& 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解释规范并将其语义内容安装到数据库中。

1 个答案:

答案 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以及为什么?

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

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