如何在Common Lisp中要求关键字参数?

时间:2016-05-25 04:55:42

标签: common-lisp keyword-argument

鉴于

(defun show-arg (a)
  (format t "a is ~a~%" a))

(defun show-key (&key a)
  (format t "a is ~a~%" a))

评估

(show-arg)

将导致错误说"参数数量无效:0",其中

(show-key)

将显示a is NIL

如何让SHOW-KEY发出SHOW-ARG之类的错误信号?除了在函数体中使用(unless a (error "a is required"))之外,还有其他方法吗?我非常喜欢关键字参数并且经常使用它们,并且几乎总是希望它们是必需的。

2 个答案:

答案 0 :(得分:10)

关键字参数始终是可选的,因此您需要手动检查是否已给出并在需要时发出错误信号。不过最好不要求关键字参数。编译器不会根据需要识别它们,因此在编译时没有给出错误消息的错误消息。

如果您确实想要它们,可以使用三元素列表指定参数;第一个元素是参数,第二个元素是默认值,第三个元素是一个变量,如果给出了参数,它将为true。检查第三个元素比检查关键字本身更好,因为这样你就可以区分默认的NIL和用户作为参数的NIL

(defun foo (&key (keyarg nil keyargp))
  (unless keyargp (error "KEYARG is required."))
  (* keyarg 2))

修改

现在我想到了这一点,实际上有一种方法可以获得缺少关键字参数的编译时错误。为函数定义编译器宏:

(defun foo (&key a b c d)
  (* a b c d))

(define-compiler-macro foo (&whole whole &key (a nil ap) (b nil bp)
                                   (c nil cp) (d nil dp))
  (declare (ignore a b c d))
  (unless (and ap bp cp dp)
    (error "Missing arguments..."))
  whole)

答案 1 :(得分:7)

一种可能性是:

(defun foo (&key (arg1 (error "missing arg1 in call to function foo")))
   arg1)

使用它:

CL-USER 80 > (foo)

Error: missing arg1 in call to function foo
  1 (abort) Return to level 0.
  2 Return to top loop level 0.

这将在运行时发出错误,遗憾的是不是在编译时。