Search code examples
clojurefunctional-programmingclojure-repl

"Can only recur from tail position, compiling" error while using recur in loop


I'm very newbie with Clojure, and for practice I am trying to apply a simple algorithm for semi random numbers.

A few days ago, I read about loops in the docs of clojure, and how they work using recur, so I tried to write a loop with this lines of code:

(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))    
))))

But when I execute the code, this error is displayed

CompilerException java.lang.UnsupportedOperationException: Can only recur from tail position, compiling

What's happening? recur is not in the tail of the function?


Solution

  • The tail position is the last form that needs to be evaluated before leaving scope. When using loop, the recur statement must be able to start fresh with new bindings, no further calculations from the previous loop left to be done.

    In your code, you have a while block in the tail position of the loop. The place where you try to call recur is not in the loop's tail position (though it is in the tail of its tail).

    Perhaps you intended for the recur call to be outside the while? But the comparison of loop bindings Xn and count to the global variable m in the test for while makes me think there is more to be untangled here. How many nested loops do you want here?