2013-01-11 56 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

此问题中的代码仅用于讨论目的。它来源于一个更大的宏。 –