【问题标题】:Clojure recursive macro expansion in the replrepl 中的 Clojure 递归宏扩展
【发布时间】:2015-11-15 17:40:02
【问题描述】:

这是一个简化的示例,问题的重点是了解如何调试递归宏以及了解宏扩展在 REPL 中的工作原理。

这是我粘贴到lein repl 的示例代码:

(defn f1 [& params] (map inc params))

(defmacro a [x]
  (if (= (count x) 0)
    ()
    (let [first-x (first x)]
      (if (= (count x) 1)
        `(f1 ~first-x)
        (let [rest-x (rest x)]
          `((f1 ~first-x) (a ~rest-x)))))))

这是我得到的:

user=> (f1 3)
(4)
user=> (f1 2 3 4)
(3 4 5)
user=> (macroexpand '(a ()))
()
user=> (macroexpand '(a (12)))
(user/f1 12)
user=> (macroexpand '(a (8 14)))
((user/f1 8) (user/a (14)))
user=> (macroexpand-all '(a (8 14)))

CompilerException java.lang.RuntimeException: Unable to resolve symbol: macroexpand-all in this context, compiling:(/tmp/form-init1519958991634351316.clj:1:1) 
user=> 

f1 函数只是增加值,这是一个简化的演示示例。

macroexpand '(a ()))(macroexpand '(a (12))) 行符合我的要求。

问题部分来了:

我该如何解决这个问题,所以 (macroexpand '(a (8 14))) 将评估为

((user/f1 8) (user/f1 14))

repl 并不停在这里扩展:

((user/f1 8) (user/a (14)))

我也尝试了 macroexpand-all,但它抛出,见上文。

【问题讨论】:

  • macroexpand-all 在 clojure.walk 中,您需要通过该命名空间访问它。
  • 解决了它。多谢。你为什么不把你的评论作为答案,这样我就可以接受了

标签: recursion clojure macros leiningen read-eval-print-loop


【解决方案1】:

您需要 clojure.walk/macroexpand-all,它可以在 clojure.walk 命名空间中找到,它是 clojure.core 的一部分。

问题的最后一部分现在有效:

user=> (clojure.walk/macroexpand-all '(a (8 14)))
((user/f1 8) (user/f1 14))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-31
    • 1970-01-01
    • 2013-12-09
    • 2016-07-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多