我如何展平传递给recur的参数?
我正在尝试了解loop/recur. 我想将函数的返回向量传递回循环,我尝试过这样的事情:
(defn foo [x y]
[(dec x) y])
(loop [x 3 y 4]
(if (> x 0)
(do
(prn x y)
(recur (foo x y)))))
这给出了:
1. Caused by java.lang.IllegalArgumentException
Mismatched argument count to recur, expected: 2 args, got: 1
现在我可以将循环参数更改为另一种有效的形式:
(defn foo [x y]
[(dec x) y])
(loop [[x y] [3 4]]
(if (> x 0)
(do
(prn x y)
(recur (foo x y)))))
我想知道是否有任何方法可以更改第一个代码以离开(loop [x 3 y 4] ...)但更改以recur某种方式传递给的参数。我想我需要类似apply函数的东西,但我无法使用它recur,因为recur它不是函数。
回答
没有简单的方法可以解决。 recur是一种特殊的形式,Clojures 绕过 JVM 的方式不容易获得 TCO。
因此,您不能apply在此处使用(这将是使用列表中的参数调用函数的解决方案)。
所以你必须坚持结果,foo然后recur与那些。注意旁边:if只有一个分支是 just when。
(defn foo [x y]
[(dec x) y])
(loop [x 3 y 4]
(when (> x 0)
(prn x y)
(let [[x' y'] (foo x y)]
(recur x' y'))))
如果你的领域真的是[x y](例如坐标),我的建议是围绕它构建你的函数,不要在有时使用向量和有时传递 x/y 之间跳转。