recursion - 如何避免 Clojure 中每个宏递归的附加括号级别

标签 recursion clojure macros lisp

我有这个递归宏 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))))))

问题似乎是每次调用都返回一个列表,它添加了另一对 () 我还尝试开发一些 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))

关于recursion - 如何避免 Clojure 中每个宏递归的附加括号级别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33724475/

相关文章:

jQuery 太多递归

javascript - 我是否遭受了过多的递归? JQuery - 在某些情况下必须点击按钮两次

performance - 在 Julia 中优化递归函数

recursion - 用于计算组合的尾递归 Clojure 函数

compilation - OpenMP 宏如何在幕后与预处理器/编译器和库本身协作?

java - 递归代码无法正常工作

clojure - Clojure 是否需要 JDK?

clojure - Rebol 中与 Clojure 映射/应用表达式最接近的匹配是什么?

c - C 中的可变函数重载

include - SAS V9.1.3 - 组合 %INC 和 CALL EXECUTE 时出错