"只能从尾部位置重复,编译"错误,同时使用循环中的重复

Fer*_*osg 1 functional-programming clojure clojure-repl

我是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))    
))))
Run Code Online (Sandbox Code Playgroud)

但是当我执行代码时,会显示此错误

CompilerException java.lang.UnsupportedOperationException: Can only recur from tail position, compiling
Run Code Online (Sandbox Code Playgroud)

发生了什么?recur是不是在功能的尾部?

Mic*_*zyk 6

似乎你的意图可能是通过使用when代替来实现的while(你的循环会继续打印更新值,Xn直到满足条件),但是要解释异常:

从编译器的角度来看,问题是虽然while表单确实处于相对于你的尾部位置loop,但是while宏的扩展是这样的,即while身体中没有任何东西相对于while表单处于尾部位置.(如果身体处于尾部位置while,那么它也会处于封闭的尾部位置loop.)

这样做的原因是while扩展到loop表达式并recur在用户提供的主体之后提供它自己:

(while test
  body...)

;; expands to

(loop []
  (when test
    body...
    (recur)))
Run Code Online (Sandbox Code Playgroud)

所以,如果你提供一个recur身体的一部分while,你得到的是

(loop []
  (when test
    ...
    (recur ...) ; from user code
    (recur)))
Run Code Online (Sandbox Code Playgroud)

这里用户提供(recur ...)的不是关于它立即封闭的尾部位置loop,这是编译器抱怨的.