Function 如何使用&;主要及;在一起休息?

Function 如何使用&;主要及;在一起休息?,function,elisp,Function,Elisp,我有一个这样的函数 (cl-defun foo (a b c d e &rest f) nil) 参数c、d和e在80%的时间内为nil 为了让它看起来更好,我会这样做: (cl-defun foo (a b &rest f &key c d e &allow-other-keys) nil) 如果未提供c、d和e,则可以 但是,如果使用其中一个参数,f会得到错误的参数。 例如: (foo 1 2 :c 6 3 4 5) ;; ==> expec

我有一个这样的函数

(cl-defun foo (a b c d e &rest f)
  nil)
参数
c
d
e
在80%的时间内为
nil

为了让它看起来更好,我会这样做:

(cl-defun foo (a b &rest f &key c d e &allow-other-keys)
  nil)
如果未提供
c
d
e
,则可以

但是,如果使用其中一个参数,
f
会得到错误的参数。 例如:

(foo 1 2 :c 6 3 4 5)
;; ==> expected: a=1, b=2, c=6, f= (3 4 5)
;; ==> real case: a=1, b=2, c=6, f= (:c 6 3 4 5) 

您看到的行为是CommonLisp指定的(实际上我不确定调用
(foo 12:c 6 3 4 5)
在CommonLisp中是否有效,因为我认为它会将3和5视为退化关键字,而
5
关键字缺少值)

查看通过
&rest
获得的列表,其中包含所有关键字。因此,如果你不想要它们,你必须用手把它们放下(在这一点上,你最好不要使用
&key

从列表
f
中删除键
cde
的示例:

(数字列表(键)(c d e))
(cl remf键)
根据@Stefan的建议,我想到了这个。我不太擅长宏,它有用吗

(cl-defmacro foo2 (a b &rest f &key c d e &allow-other-keys)
  (let (key rest)
    (dolist (elt f)
      (if (memq elt '(:c :d :e))
          (setq key elt)
        (if key
            (progn
              (set (intern-soft (string-remove-prefix ":" (symbol-name key))) elt)
              (setq key nil))
          (push elt rest))))
    (setq rest (nreverse rest))

    `(foo ,a ,b ,c ,d ,e ,@rest)))

(pp-macroexpand-expression '(foo2 1 2 :c 3 :d 4 :e 5 6 7 8 9))
;; ==> (foo 1 2 3 4 5 6 7 8 9)
(pp-macroexpand-expression '(foo2 1 2 3 4 5 6))
;; ==> (foo 1 2 nil nil nil 3 4 5 6)
(pp-macroexpand-expression '(foo2 1 2 3 4 5 6 :c 7 :d 8 :e 9))
;; ==> (foo 1 2 7 8 9 3 4 5 6)
(pp-macroexpand-expression '(foo2 1 2 3 :c 4 5 :d 6 7 :e 8 9))
;; Extreme case
;; ==> (foo 1 2 4 6 8 3 5 7 9)