repl中的Clojure递归宏展开
Clojure recursive macro expansion in the repl
这是一个简化的示例,问题的重点是了解如何调试递归宏以及了解 macroexpand 在 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,但它抛出错误,见上文。
您需要 clojure.walk/macroexpand-all
,它可以在 clojure.walk
命名空间中找到,它是 clojure.core 的一部分。
问题的最后一部分现在有效:
user=> (clojure.walk/macroexpand-all '(a (8 14)))
((user/f1 8) (user/f1 14))
这是一个简化的示例,问题的重点是了解如何调试递归宏以及了解 macroexpand 在 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,但它抛出错误,见上文。
您需要 clojure.walk/macroexpand-all
,它可以在 clojure.walk
命名空间中找到,它是 clojure.core 的一部分。
问题的最后一部分现在有效:
user=> (clojure.walk/macroexpand-all '(a (8 14)))
((user/f1 8) (user/f1 14))