如何展平传递的参数以重复出现?
How do I flatten params passed to recur?
我正在尝试了解 loop/recur
。我想将 return 向量从函数传回循环,我试过这样的事情:
(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
绕过无法轻松访问 TCO 的 JVM。
因此你不能在这里使用 apply
(这将是调用的解决方案
带有列表参数的函数)。
所以你必须坚持 foo
的结果,然后 recur
那些。旁注:只有一个分支的 if
就是 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.
您也可以为此目的编写一个简单的宏。可能像这样(这基本上是对矢量化参数变体的宏重写):
(defmacro loop1 [bindings & body]
(let [left-side (vec (take-nth 2 bindings))
right-side (vec (take-nth 2 (rest bindings)))]
`(loop [~left-side ~right-side]
~@body)))
(loop1 [x 3 y 4]
(if (> x 0)
(do
(prn x y)
(recur (foo x y)))))
;;=> 3 4
;; 2 4
;; 1 4
nil
所以,如果您有类似的重复使用模式,这个宏可能是一个不错的实用程序。
我正在尝试了解 loop/recur
。我想将 return 向量从函数传回循环,我试过这样的事情:
(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
绕过无法轻松访问 TCO 的 JVM。
因此你不能在这里使用 apply
(这将是调用的解决方案
带有列表参数的函数)。
所以你必须坚持 foo
的结果,然后 recur
那些。旁注:只有一个分支的 if
就是 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.
您也可以为此目的编写一个简单的宏。可能像这样(这基本上是对矢量化参数变体的宏重写):
(defmacro loop1 [bindings & body]
(let [left-side (vec (take-nth 2 bindings))
right-side (vec (take-nth 2 (rest bindings)))]
`(loop [~left-side ~right-side]
~@body)))
(loop1 [x 3 y 4]
(if (> x 0)
(do
(prn x y)
(recur (foo x y)))))
;;=> 3 4
;; 2 4
;; 1 4
nil
所以,如果您有类似的重复使用模式,这个宏可能是一个不错的实用程序。