I have some code that’s currently giving me an error, because recur can only be in the tail position. here’s the function:
(defmethod transposer
Long [scale degree]
(loop [new-scale scale count degree]
(cond
(zero? count) new-scale
(< count 0) (recur (step (reverse new-scale)) (inc count)))
:else (recur (step new-scale) (dec count))))
One way I can think to fix this is conditional binding, if I could say:
when count is less than zero, set count-operator to “inc”, otherwise set to “dec”, then recur at the end.
Then this would fix my problem. But I’m not sure how to do this in clojure, or if it’s even possible, when-let and if-let don’t seem to do this. What is the best way to fix my code to only use one recur?
EDIT: A couple of things I learned here:
1) “recur” will recur back to the defn, if there’s no loop statement. In the book I read, all the examples of recur use loop/recur, so I thought it was necessary to have a loop. it’s not, my loop statement want superfluous.
2) Getting the parentheses wrong gave me a confusing error, it struck me as strange that both cond statements wouldn’t be considered to be at the tail, since they are mutually exclusive. I should have paid a bit more attention to my paren completion checker.
3) If I ever do want to do conditional binding, I can use a standard “let” statement and just include the conditional logic there. coming from a java background, I sometimes forget the flexibility clojure allows in this area.
is closer to what you want, i think (it doesn’t give the tail error; i used defn simply to test standalone).
there is no problem with multiple
recurs – tail recursion doesn’t mean it has to be on the last line of text, only that there is no more calculation to do when it returns.the main problem was messed up parens (too many after
count). i’d suggest getting an editor that auto-indents (and using auto-indent obsessively). that would have shown the parens problem immediately (i use la clojure plugin in intellij idea, but i am sure others have similar functionality).update: why is the
loopneeded at all?