"Can only recur from tail position, compiling" 在循环中使用 recur 时出错
"Can only recur from tail position, compiling" error while using recur in loop
我是 Clojure 的新手,为了练习,我尝试对半随机数应用一个简单的算法。
几天前,我在 clojure 的文档中了解到循环,以及它们如何使用 recur
,所以我尝试用这行代码编写一个循环:
(def numbers_semi_random
(fn []
(loop[Xn 4 count 0]
(while (and (not (= Xn m)) (< count m))
(println (mod (+ (* 5.0 Xn) 7.0) m))
(recur (mod (+ (* 5.0 Xn) 7.0) m) (inc count))
))))
但是当我执行代码时,显示这个错误
CompilerException java.lang.UnsupportedOperationException: Can only recur from tail position, compiling
发生什么事了? recur
是不是在函数的尾部?
尾部位置是在离开作用域之前需要计算的最后一个形式。使用 loop
时,recur
语句必须能够使用新的绑定重新开始,之前循环中没有进一步的计算需要完成。
在您的代码中,loop
的尾部位置有一个 while
块。您尝试调用 recur
的地方不在循环的尾部位置(尽管它在其尾部的尾部)。
也许您打算让 recur
调用在 while
之外?但是在 while
的测试中,循环绑定 Xn
和 count
与全局变量 m
的比较让我觉得这里还有更多需要解决的问题。您想要多少个嵌套循环?
您的意图似乎可以通过使用 when
代替 while
来实现(然后您的循环将继续打印 Xn
的更新值,直到满足条件) ,但要解释异常:
从编译器的角度来看,问题是虽然 while
形式确实位于 loop
的尾部位置,但 while
宏的扩展是这样的while
的正文中没有任何内容位于 while
形式的尾部位置。 (如果正文处于尾部位置 w.r.t。while
形式,它也将处于尾部位置 w.r.t。封闭 loop
。)
之所以如此,是因为 while
扩展为 loop
表达式并在用户提供的正文之后提供了自己的 recur
:
(while test
body...)
;; expands to
(loop []
(when test
body...
(recur)))
因此,如果您提供 recur
作为 while
正文的一部分,您得到的是
(loop []
(when test
...
(recur ...) ; from user code
(recur)))
此处用户提供的 (recur ...)
相对于其立即包含的 loop
不在尾部位置,这就是编译器所抱怨的。
我是 Clojure 的新手,为了练习,我尝试对半随机数应用一个简单的算法。
几天前,我在 clojure 的文档中了解到循环,以及它们如何使用 recur
,所以我尝试用这行代码编写一个循环:
(def numbers_semi_random
(fn []
(loop[Xn 4 count 0]
(while (and (not (= Xn m)) (< count m))
(println (mod (+ (* 5.0 Xn) 7.0) m))
(recur (mod (+ (* 5.0 Xn) 7.0) m) (inc count))
))))
但是当我执行代码时,显示这个错误
CompilerException java.lang.UnsupportedOperationException: Can only recur from tail position, compiling
发生什么事了? recur
是不是在函数的尾部?
尾部位置是在离开作用域之前需要计算的最后一个形式。使用 loop
时,recur
语句必须能够使用新的绑定重新开始,之前循环中没有进一步的计算需要完成。
在您的代码中,loop
的尾部位置有一个 while
块。您尝试调用 recur
的地方不在循环的尾部位置(尽管它在其尾部的尾部)。
也许您打算让 recur
调用在 while
之外?但是在 while
的测试中,循环绑定 Xn
和 count
与全局变量 m
的比较让我觉得这里还有更多需要解决的问题。您想要多少个嵌套循环?
您的意图似乎可以通过使用 when
代替 while
来实现(然后您的循环将继续打印 Xn
的更新值,直到满足条件) ,但要解释异常:
从编译器的角度来看,问题是虽然 while
形式确实位于 loop
的尾部位置,但 while
宏的扩展是这样的while
的正文中没有任何内容位于 while
形式的尾部位置。 (如果正文处于尾部位置 w.r.t。while
形式,它也将处于尾部位置 w.r.t。封闭 loop
。)
之所以如此,是因为 while
扩展为 loop
表达式并在用户提供的正文之后提供了自己的 recur
:
(while test
body...)
;; expands to
(loop []
(when test
body...
(recur)))
因此,如果您提供 recur
作为 while
正文的一部分,您得到的是
(loop []
(when test
...
(recur ...) ; from user code
(recur)))
此处用户提供的 (recur ...)
相对于其立即包含的 loop
不在尾部位置,这就是编译器所抱怨的。