2016-04-14 35 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) 

有了@斯蒂芬的建議,我想出了這個。我不擅長宏觀,它的工作?

相關問題