2015-04-20 105 views
1

我想創建一個宏,以便我可以在變量本身中添加變量名。我有這個Unit的記錄。其name成員存儲將創建的變量的名稱。 即(def a-variable (->Unit 1 1 "a-varible")) 但我不想自己傳遞變量名稱。Clojure宏:在宏內部執行代碼

我認爲宏可以派上用場。 :)

下面是代碼:

(defrecord Unit 
    [value gradient name] 
    Object 
    (toString [_] 
    (str name " : "))) 


(defmacro create-unit1 [var-name & body] 
    `(def ~var-name ~(concat body (list (name var-name))))) 

(defmacro create-unit2 [var-name & body] 
    `(def ~var-name (concat [email protected] (list (name '~var-name))))) 

但他們都不是給我寫代碼:

neurals.core> (macroexpand '(create-unit1 a (->Unit 1.0 0.0))) 
(def a ((->Unit 1.0 0.0) "a")) 

neurals.core> (macroexpand '(create-unit2 a (->Unit 1.0 0.0))) 
(def a (clojure.core/concat 
     (->Unit 1.0 0.0) (clojure.core/list 
          (clojure.core/name (quote a))))) 
neurals.core> 

我想:

(def a (->Unit 1.0 0.0 (clojure.core/name (quote a)))) 

什麼是正確的方式在宏內執行concat

回答

2

您可以通過刪除解決您的代碼&create-unit1

(defmacro create-unit1 [var-name body] 
    `(def ~var-name ~(concat body (list (name var-name))))) 

(macroexpand `(create-unit1 a (->Unit 1.0 1.0))) 
;; => (def user/a (user/->Unit 1.0 1.0 "a")) 

您還可以添加的語法糖一點點:

(defmacro create-unit1 [var-name body] 
    `(def ~var-name ([email protected] ~(name var-name)))) 

或者,讓這一切更地道:

(defmacro defunit [sym value gradient] 
    `(def ~sym (->Unit ~value ~gradient ~(name sym)))) 

(defunit a 1.0 1.0) 
;; => #user.Unit{:value 1.0, :gradient 1.0, :name "a"} 
+0

哦〜(〜@ body〜(name var-name))''是連接它的方法:) ..涼 –