【问题标题】:clojure macro variable trouble with mapclojure 宏变量与地图的问题
【发布时间】:2013-01-11 03:26:32
【问题描述】:

我无法让 clojure defmacro 执行我想要的操作。我已将我的实际代码缩减为以下 sn-p。

这会创造出我想要的东西接近。我正在尝试根据传递给宏的参数有条件地插入(第一个 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_18340_auto_)与匿名函数参数 p_18341_auto_ 不匹配.因此,执行代码会导致错误,因为未定义第二个 var。我怎样才能让这些变量匹配?这就是我想要完成的。

出于测试目的,此代码完成我想要的,但我想要设置 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))

表演

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

【问题讨论】:

标签: clojure


【解决方案1】:

解决方案之一

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

您可以将if 分支中的(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] ])))

【讨论】:

  • 您已经回答了上述问题,因为它有效。但是,我不确定它是否修复了我感兴趣的完整案例。它的文本不仅仅是“第一与”第二。您可以在此处突出显示的行中看到这一点:gist.github.com/4506057#file-stringed-clj-L78-L83 我会考虑一下,看看我是否可以以某种方式使用您的解决方案...
  • 再次感谢,这看起来很有希望!
  • @RogerAllen 我添加了更简单的解决方案。
  • 酷。我认为第二种解决方案最适合我的情况。该代码似乎正在工作。给你打勾——再次感谢!
【解决方案2】:

必须声明,这根本不需要是宏。

函数等价物更易读,更可组合,所以我建议你使用它。

【讨论】:

  • 本题代码仅供讨论。它源自一个更大的宏。
猜你喜欢
  • 2023-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-12
  • 1970-01-01
相关资源
最近更新 更多