2011-09-05 2 views
6

Я пытаюсь написать макрос в Clojure, который позволяет оценивать ряд простых выражений «def». Я n00b, когда дело доходит до макросов. Идея заключается в том, чтоЦитирование макросов макросов

(my-defs y1 1 
    y2 "taco") 

следует расширить до

(do (def y1 1) (def y2 "taco")) 

Следующий код выполняет это для особого случая двух DEFS

(defmacro my-defs 
    [& args] 
    `(do 
    (def ~(first args) ~(second args)) 
    (def ~(nth args 2) ~(nth args 3)))) 

который хорош, но у меня возникают проблемы, обобщающее это. Я опробовал несколько наивных вещей, связанных с переплетением элементов из (partition 2 args), но у меня всегда был мусор (я знаю, что это не очень специфично, но разнообразие и степень мусора казались слишком сложными, чтобы сообщить об этом здесь). Как это сделать, и оценить мои определения?

P.S. Макрос my-defs является игрушкой. То, что я действительно хочу сделать в конце, - вспомогательный макрос littel для создания экземпляра мультиметодов. В настоящее время у меня есть большие куски кода, которые выглядят как

(defmethod f [A B] [x] "AB") 
(defmethod f [A A] [x] "AA") 
(defmethod f [C B] [x] "CB") 

, который немного неприглядный. Было бы неплохо, если бы я мог сделать что-то вроде

(defmethods f 
    [A B] [x] "AB" 
    [A A] [x] "AA" 
    [C B] [x] "CB") 

вместо этого.

ответ

5

Это выглядит так, как будто вы ищете расширение макроса ~ @ unquote.

(defmacro defmethods [n & defs] 
    `(do [email protected](map (fn [[a1 a2 a3]] 
        `(def ~n ~a1 ~a2 ~a3)) 
       (partition 3 defs)))) 
+0

Спасибо, я написал свои defmethods сейчас! –

+1

Я думаю, что этот шаблон легче написать как '(cons 'do (для [[xyz] (partition 3 args)] ...)' или '\' (do ~ @ (for ...)) \ ' «Карта разрывает поток вещей, а использование backquote и' ~ @ 'просто для получения недостатков делает код запутанным. – amalloy

+0

@amalloy. Спасибо за подсказку. (Do ~ @ (for ...)) выглядит лучше. –