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

Common lisp 如何在公共Lisp中要求关键字参数?,common-lisp,keyword-argument,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)) 将导致显示“无效参数数:0”的错误,其中 将显示a为零 如何让SHOW-KEY发出错误信号,如SHOW-ARGdoes?除了在函数体中使用(除非有(错误“a是必需的”),还有其他方法吗?我非常喜欢关键字参数并经常使用它们,而且几乎总是希望它们是必需的。关键字参数总是可选的,

给定

评估

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

(defun show-key (&key a)
  (format t "a is ~a~%" a))
将导致显示“无效参数数:0”的错误,其中

将显示
a为零


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

关键字参数总是可选的,因此您需要手动检查它们是否已给出,如果需要,则发出错误信号。不过,最好不要使用关键字参数。编译器不会根据需要识别它们,因此不会在编译时向您提供缺少参数的错误消息

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

(show-key)
编辑

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

(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)
使用它:

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

这将在运行时产生错误,不幸的是不是在编译时。

这方面的一个小变体是将错误的信号包装到一个小函数中,这样您就可以说
&key(foo(required))
“不过最好不需要关键字参数。”建议的方法是什么,例如初始化具有许多必填字段的记录?例如,我如何提高
(制作专辑“Led齐柏林飞艇”“物理涂鸦”1979 nil t'rock)
?@leo狂躁者通常会尝试提供有意义的默认值,用户只会在必要时覆盖它们。在该示例中,前两个参数可能是唯一必需的参数,其余参数可以保留为
NIL
。在大多数实际程序中,这对可读性来说并不是一个真正的问题,因为很少用文本值初始化记录。您通常会从文件/数据库/用户读取值,变量名会让读者明白它们的含义。他们还可以使用自己的开发环境(如SLIME)查看参数列表。
(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.