【问题标题】:How to require keyword arguments in Common Lisp?如何在 Common Lisp 中要求关键字参数?
【发布时间】:2016-05-25 04:55:41
【问题描述】:

给定

(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-KEYSHOW-ARG 一样发出错误信号?除了在函数体中使用(unless a (error "a is required")),还有其他方法吗?我非常喜欢关键字参数并经常使用它们,并且几乎总是希望它们是必需的。

【问题讨论】:

    标签: common-lisp keyword-argument


    【解决方案1】:

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

    如果您确实需要它们,可以使用三元素列表指定参数;第一个元素是参数,第二个是默认值,第三个是一个变量,如果给定了参数,它将为真。检查第三个元素比检查关键字本身要好,因为这样您就可以区分默认的 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)
    

    【讨论】:

    • "最好不要使用关键字参数。"建议的方法是什么?用许多必填字段初始化记录?例如。如何提高 (make-album "Led Zeppelin" "Physical Graffiti" 1979 nil t 'rock) 之类的可读性?
    • @leo-the-manic 通常您会尝试提供有意义的默认值,而用户只会在必要时覆盖它们。在该示例中,前两个可能是唯一需要的参数,其余的可以保留为NIL。在大多数实际程序中,这对于可读性来说并不是真正的问题,因为很少使用文字值初始化记录。您通常会从文件/数据库/用户中读取值,并且变量名称将使读者清楚它们的含义。他们还可以使用 SLIME 等开发环境来查看参数列表。
    【解决方案2】:

    一种可能性是:

    (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.
    

    这会在运行时出错,不幸的是在编译时不会。

    【讨论】:

    • 对此的一个小变种是将错误信号包装到一个小函数中,以便您可以说&key (foo (required))
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-07-14
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 2012-12-11
    • 2021-02-15
    • 1970-01-01
    相关资源
    最近更新 更多