2016-04-14 40 views
0

我有这样如何在cl-defun togather中使用&key和&rest?

(cl-defun foo (a b c d e &rest f) 
    nil) 

参数cde功能是时间nil 80%。

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

(cl-defun foo (a b &rest f &key c d e &allow-other-keys) 
    nil) 

当不提供cde,它的罚款。

但是,如果使用其中之一,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) 

回答

0

您所看到的行为是CommonLisp(其实我不知道,因为我认为它会像对待3和5退化您的通话(foo 1 2 :c 6 3 4 5)即使在CommonLisp有效的指定的一个关键字5关键字缺少值)。

不管你通过&rest获得的列表都包含了所有关键字。所以如果你不想要它们,你必须手工放下它们(在这一点上你通常最好不要使用&key)。

0
(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) 

有了@斯蒂芬的建议,我想出了这个。我不擅长宏观,它的工作?

相关问题