Confused about trampoline

clojure

#1

Can someone help me understand trampoline ?
It looks to me like the clojure.core implementation of trampoline continues to call the return value of the given designated function, as long as it keeps returning a function as determined by fn?. So how am I supposed to make the function actually return a function which I don’t intend to be a tail call? Do I need to write that version of trampoline, or is there an option in closure.core.trampoline for this?

For example, how can I convert the following to use trampoline ?

(declare funa funb)

(defn funa [n]
  (if (= n 0)
    first
    (funb (dec n))))

(defn funb [n]
  (if (= n 0)
    second
    (funa (dec n))))

If I do this the way recommended by Understanding the Clojure `trampoline’,

user=> (declare funa funb)
#'user/funb
user=> (defn funa [n] (if (= n 0) first #(funb (dec n))))
#'user/funa
user=> (defn funb [n] (if (= n 0) second #(funa (dec n))))
#'user/funb
user=> (trampoline funa 100)
Execution error (ArityException) at user/eval149 (REPL:1).
Wrong number of args (0) passed to: clojure.core/first--5369

#2
(declare funa funb)
=> #'user/funb
(defn funa [n] (if (= n 0) (reduced first) #(funb (dec n))))
=> #'user/funa
(defn funb [n] (if (= n 0) (reduced second) #(funa (dec n))))
=> #'user/funb
@(trampoline funa 100)
=>
#object[clojure.core$first__5369 0x77e3382d "[email protected]"]

#3

As trampoline's documentation states, 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.