如何避免 Clojure 中每个宏递归的附加括号级别
How to avoid additional parenthesis level on each macro recursion in Clojure
我有这个递归宏 m1
,它被宏 m1-do
调用。目的是生成一些函数调用。
(defmacro m1 [fname x]
(if (= (count x) 1)
(let [a0 (first x)]
`(~fname ~a0))
(let [[a0 & arest] x]
`((~fname ~a0) (m1 ~fname ~arest)))))
(defmacro m1-do [fname x]
`(do (m1 ~fname ~x)))
这就是我想要达到的结果:
(m1-do f1 (45 98 122 143 215)) =>
(do (f1 45) (f1 98) (f1 122) (f1 143) (f1 215))
但是我在每次递归时都得到了一个额外的括号级别。第一个结果已经有太多:
user=> (clojure.walk/macroexpand-all '(m1-do f1 (45 98)))
(do ((f1 45) (f1 98)))
user=> (clojure.walk/macroexpand-all '(m1-do f1 (45 98 122)))
(do ((f1 45) ((f1 98) (f1 122))))
user=> (clojure.walk/macroexpand-all '(m1-do f1 (45 98 122 143)))
(do ((f1 45) ((f1 98) ((f1 122) (f1 143)))))
user=> (clojure.walk/macroexpand-all '(m1-do f1 (45 98 122 143 215)))
(do ((f1 45) ((f1 98) ((f1 122) ((f1 143) (f1 215))))))
问题似乎是每次调用 returns 一个列表,它会添加另一对 ()
我也尝试开发一些 flattening
函数并在没有宏的情况下使用它成功。
数字只是实际内容的占位符,更复杂。
你可以用一个非常简单的非递归宏来完成:
(defmacro m1-do [fname coll]
`(do ~@(map (partial list fname) coll)))
以下是如何使用 cons
做同样的事情:
(defmacro m1-do [fname coll]
(cons 'do (map (partial list fname) coll)))
两个版本完全相同并产生期望输出:
(macroexpand '(m1-do f1 (45 98 122 143 215)))
; => (do (f1 45) (f1 98) (f1 122) (f1 143) (f1 215))
我有这个递归宏 m1
,它被宏 m1-do
调用。目的是生成一些函数调用。
(defmacro m1 [fname x]
(if (= (count x) 1)
(let [a0 (first x)]
`(~fname ~a0))
(let [[a0 & arest] x]
`((~fname ~a0) (m1 ~fname ~arest)))))
(defmacro m1-do [fname x]
`(do (m1 ~fname ~x)))
这就是我想要达到的结果:
(m1-do f1 (45 98 122 143 215)) =>
(do (f1 45) (f1 98) (f1 122) (f1 143) (f1 215))
但是我在每次递归时都得到了一个额外的括号级别。第一个结果已经有太多:
user=> (clojure.walk/macroexpand-all '(m1-do f1 (45 98)))
(do ((f1 45) (f1 98)))
user=> (clojure.walk/macroexpand-all '(m1-do f1 (45 98 122)))
(do ((f1 45) ((f1 98) (f1 122))))
user=> (clojure.walk/macroexpand-all '(m1-do f1 (45 98 122 143)))
(do ((f1 45) ((f1 98) ((f1 122) (f1 143)))))
user=> (clojure.walk/macroexpand-all '(m1-do f1 (45 98 122 143 215)))
(do ((f1 45) ((f1 98) ((f1 122) ((f1 143) (f1 215))))))
问题似乎是每次调用 returns 一个列表,它会添加另一对 ()
我也尝试开发一些 flattening
函数并在没有宏的情况下使用它成功。
数字只是实际内容的占位符,更复杂。
你可以用一个非常简单的非递归宏来完成:
(defmacro m1-do [fname coll]
`(do ~@(map (partial list fname) coll)))
以下是如何使用 cons
做同样的事情:
(defmacro m1-do [fname coll]
(cons 'do (map (partial list fname) coll)))
两个版本完全相同并产生期望输出:
(macroexpand '(m1-do f1 (45 98 122 143 215)))
; => (do (f1 45) (f1 98) (f1 122) (f1 143) (f1 215))