2013-01-11 57 views
2

我無法讓clojure defmacro做我想做的事。我已將我的實際代碼縮減爲以下代碼段。clojure宏變量與地圖的麻煩

這創造了一些東西關閉到我想要的。我試圖有條件地插入(第一個p#)或(第二個p#),具體取決於傳遞給宏的參數。

(defmacro mmz1 [t] 
    `(map (fn [p#] (let [t1# (first p#) 
         t2# ~(if t `(first p#) `(second p#))] 
        (* t1# t2#))) 
     [ [1 2] [3 4] ])) 

(macroexpand-1 '(mmz1 false)) 

顯示

(map 
    (fn [p__18341__auto__] 
    (let [t1__18342__auto__ (first p__18341__auto__) 
      t2__18343__auto__ (second p__18340__auto__)] 
     (* t1__18342__auto__ t2__18343__auto__))) 
    [[1 2] [3 4]]) 

但是,請注意,這種形式的變量(第二P_ _auto_ )不匹配匿名函數參數p _18341_ 汽車 _。所以,執行代碼會導致錯誤,因爲第二個var沒有定義。我怎樣才能讓這些變量匹配?這是我想要完成的。

出於測試目的,該代碼完成我想要的,但我想在那臺T2#產生的宏代碼(如果)的形式。一個宏應該讓我做到這一點 - 不是嗎?

(defmacro mmz0 [t] 
    `(map (fn [p#] (let [t1# (first p#) 
         t2# (if ~t (first p#) (second p#))] 
        (* t1# t2#))) 
     [ [1 2] [3 4] ])) 

(macroexpand-1 '(mmz0 false)) 

顯示

(map 
    (fn [p__18387__auto__] 
    (let [t1__18388__auto__ (first p__18387__auto__) 
      t2__18389__auto__ (if false 
           (first p__18387__auto__) 
           (second p__18387__auto__))] 
     (* t1__18388__auto__ t2__18389__auto__))) 
    [[1 2] [3 4]]) 

和代碼的輸出是預期:

(mmz0 false) -> (2 12) 
+0

如果你想要解決這個問題的背景,我在Overtone論壇的這個查詢中解釋了它(有點)。 https://groups.google.com/forum/?fromgroups=#!topic/overtone/CScDTtzteRk –

回答

3

一種解決方案

(defmacro mmz1 [t] 
    `(map (fn [p#] (let [t1# (first p#) 
         t2# (~(if t 'first 'second) p#)] 
        (* t1# t2#))) 
     [ [1 2] [3 4] ])) 

更新的。更普遍的解決方案

(defmacro mmz1 [t] 
    (let [trg-fn (if t 
       `(fn [p#] (first p#)) 
       `(fn [p#] (second p#)))] 
    `(map (fn [p#] (let [t1# (first p#) 
         t2# (~trg-fn p#)] 
        (* t1# t2#))) 
     [ [1 2] [3 4] ]))) 

可以更換(fn [p#]...)if分行與更復雜的功能。

Update2。使用預定義的函數形式參數p

(defmacro mmz1 [t] 
    (let [p `p#] 
    `(map (fn [~p] (let [t1# (first ~p) 
         t2# ~(if t `(first ~p) `(second ~p))] 
        (* t1# t2#))) 
     [ [1 2] [3 4] ]))) 
+0

哦,那看起來不錯!謝謝mobyte! –

+0

你已經回答了這個問題,因爲這是有效的。但是,我不確定它是否解決了我感興趣的全部案例。這比第一個「第一個vs」更多。你可以看到在這裏突出顯示的行: https://gist.github.com/4506057#file-stringed-clj-L78-L83 我會考慮它,看看我能否以某種方式使用你的解決方案。 .. –

+0

@RogerAllen我已經更新了答案。 – mobyte

0

它有簡單的解決方案必須說,這已經沒有必要做個宏都沒有。

功能相當於更具可讀性和更可組合性,所以我建議您使用它。

+0

此問題中的代碼僅用於討論目的。它來源於一個更大的宏。 –