clojure宏变量与map有关

clojure宏变量与map有关,clojure,Clojure,我很难让clojure defmacro做我想做的事。我已将实际代码缩减为以下代码片段 这创造了一些接近我想要的东西。我试图根据传入宏的参数有条件地插入(第一个p#)或(第二个p#) (defmacro mmz1 [t] `(map (fn [p#] (let [t1# (first p#) t2# ~(if t `(first p#) `(second p#))] (* t1# t2#))) [

我很难让clojure defmacro做我想做的事。我已将实际代码缩减为以下代码片段

这创造了一些接近我想要的东西。我试图根据传入宏的参数有条件地插入(第一个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))
显示

但是,请注意,这种形式的变量(第二个p_18340_auto_)与匿名函数参数p_18341_auto_不匹配。因此,执行代码会导致错误,因为没有定义第二个变量。我怎样才能让这些变量匹配?这就是我想要完成的

出于测试目的,这段代码实现了我想要的功能,但我不希望结果宏代码中设置t2#的(if)形式。宏应该允许我这样做,不是吗

(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))
显示

代码的输出是预期的:

(mmz0 false) -> (2 12)
解决方案之一

(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#]…)

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] ])))

必须说明的是,这根本不需要是宏


函数等价物更具可读性和可组合性,因此我建议您使用它。

如果您想了解此问题背后的背景,我在泛音论坛上的查询中对此进行了解释。您已经回答了前面提到的问题,因为这是可行的。但是,我不确定它是否解决了我感兴趣的全部问题。这比“第一对第二”有更多的文字。你可以在这里突出显示的几行中看到这一点:我会考虑一下&看看我是否能以某种方式使用你的解决方案……再次感谢,这看起来很有希望@我添加了更简单的解决方案。酷。我认为第二种解决方案最适合我的情况。代码似乎正在运行。给你打勾--再次感谢!本问题中的代码仅供讨论之用。它来自一个更大的宏。
(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] ])))
(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] ])))