spike
spike

Reputation: 10004

Two functions which call each other recursively

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

Answers (2)

Chiron
Chiron

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

noisesmith
noisesmith

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

Related Questions