Parameters 如何将可选参数和关键字参数用于同一个函数?

Parameters 如何将可选参数和关键字参数用于同一个函数?,parameters,lisp,keyword,Parameters,Lisp,Keyword,我正在尝试编写一个Lisp函数,它可以接受可选参数和关键字参数。函数开始 (defun max-min (v &optional max min &keyword (start 0) (end nil)) 当我尝试使用关键字参数(而不是可选参数)调用函数时,会出现错误。我想做的是 (max-min #(1 2 3 4) :start 1 :end 2) 我得到的错误error::START'不是预期的类型REAL' 我假设这是因为它试图将:start绑定到max。我怎样才能让

我正在尝试编写一个Lisp函数,它可以接受可选参数和关键字参数。函数开始

(defun max-min (v &optional max min &keyword (start 0) (end nil))
当我尝试使用关键字参数(而不是可选参数)调用函数时,会出现错误。我想做的是

(max-min #(1 2 3 4) :start 1 :end 2)
我得到的错误
error::START'不是预期的类型REAL'


我假设这是因为它试图将
:start
绑定到
max
。我怎样才能让它工作?谢谢。

您需要使用所需参数、可选参数和关键字参数调用该函数。否则它应该如何工作?您的呼叫缺少可选参数。如果要在调用中指定关键字参数,则可选参数不再是可选的

(max-min #(1 2 3 4) 0 100 :start 1 :end 2)
基本样式规则:

不要在函数中将可选参数与关键字参数混合使用。例如,CommonLisp在某些地方使用它,它是bug的来源

CL:READ-FROM-STRING
就是这样一个例子

read-from-string string
                 &optional eof-error-p eof-value
                 &key start end preserve-whitespace

这项工作:

(read-from-string " 1 3 5" t nil :start 2)
这可能也适用于:

(read-from-string " 1 3 5" :start 2)

但是用户忘记指定EOF-ERROR-p和EOF-VALUE。Lisp编译器可能不会抱怨,用户会想知道为什么它不会从2开始。

为了完整起见,您可以自己解析提供的参数列表,从技术上让它工作:

(defun max-min (v &rest args)
  (flet ((consume-arg-unless-keyword (default)
           (if (keywordp (first args))
               default
               (pop args))))
    (let ((max (consume-arg-unless-keyword nil))
          (min (consume-arg-unless-keyword nil)))
      (destructuring-bind (&key (start 0) (end nil)) args
        ;; ...
        ))))
不过,像往常一样,听听雷纳的话是个好主意。这看起来太神奇了。它混淆了开发环境(例如,通过破坏自动arglist显示)和用户(通过使类型错误更难发现:当您无意中传递了一个关键字,而您想要传递一个数字时,会发生什么情况?)