下面的代碼實現了一個帶有隱式可選參數的宏調用,因爲它隱藏在& rest參數中。有沒有更好的方法來編寫宏(及其支持函數) - 可能通過使用&可選關鍵字(或者其他方式)使可選參數顯式化?最好是第一個參數是必需的,第二個是可選的,並且需要許多其餘的參數。也希望保留宏定義簡單,由支撐作用所做的工作,如果可能的話(但想學習更多先進的方法太):按順序指定可選參數
(defstruct action
name duration slot1 slot2 slot3)
(defmacro define-action (name &rest rest)
`(install-action ',name ',rest))
(defun install-action (name &rest rest)
(let* ((slots (first rest))
(duration (if (numberp (first slots))
(prog1 (first slots)
(setf slots (cdr slots)))
0))
(action (make-action :name name :duration duration
:slot1 (first slots) :slot2 (second slots)
:slot3 (third slots))))
(print action)))
(define-action move a b c) ;first example no duration
(define-action move 1 a b c) ;second example with duration=1
#S(ACTION :NAME MOVE :DURATION 0 :SLOT1 A :SLOT2 B :SLOT3 C)
#S(ACTION :NAME MOVE :DURATION 1 :SLOT1 A :SLOT2 B :SLOT3 C)
澄清的附加點:上面的槽值是真的不同規範表示爲(有時深度嵌套)lisp樹。函數install-action解釋規範並將其語義內容安裝到數據庫中。
如果其他參數是必需的,最好使它們成爲常規的命名參數。這樣,宏的用戶可以從lambda列表中看到他們應該給它的內容,而不必猜測(/閱讀文檔)。可選的持續時間可以是最後的關鍵字/可選參數。或者你可以爲宏指定'(name(&optional(duration 0))slot1 slot2 slot3)'。 – jkiiski
如果我能使用它,我寧願使用您的解決方案。 (不知道必填項/可選項可能會混在一起)你如何得到 (defmacro define-action(name(&optional(duration 0))slot1 slot2 slot3) '(install-action',name',duration ',slot1',slot2',slot3)) to macroexpand properly? (ps:如何在Stackoverflow上記錄註釋的首選解決方案?) – davypough
這應該起作用:'(macroexpand'(define-action foo(3)abc))'=>'(INSTALL-ACTION'FOO'3' A'B'C)'。請記住,您必須將持續時間放在身邊(如果您沒有持續時間,則必須將空閒的身體放置)。 – jkiiski