Reputation: 10004
Is it possible to define two functions in clojure which recursively call each other? For example, this pair:
(defn a [x]
(if (= 0 x) 0 (b (dec x))))
(defn b [x]
(if (= 0 x) 0 (a (dec x))))
Compilation fails with:
Unable to resolve symbol: b in this context
Since I haven't defined b
when I try to call it in a
.
e.g., in ruby this works fine:
def a(x)
x == 0 ? x : b(x-1)
end
def b(x)
x == 0 ? x : a(x-1)
end
Upvotes: 8
Views: 1570
Reputation: 20245
Depending on the execution of your code, keep in mind that you might get stack overflow exception.
There is where (clojure.core/trampoline) function come into the play and do its magic.
trampoline can be used to convert algorithms requiring mutual recursion without stack consumption. Calls f with supplied args, if any. If f returns a fn, calls that fn with no arguments, and continues to repeat, until the return value is not a fn, then returns that non-fn value. Note that if you want to return a fn as a final value, you must wrap it in some data structure and unpack it after trampoline returns.
Upvotes: 6
Reputation: 20194
either:
(declare b)
... ; rest of your code can then be used as is
or:
(def mutual
(letfn [(a [ ... ] ...)
(b [ ... ] ...)]
[a b]))
(def a (first mutual))
(def b (second mutual))
Upvotes: 7