7

是否可以在 clojure 中定义两个递归调用的函数?例如,这对:

(defn a [x]
  (if (= 0 x) 0 (b (dec x))))

(defn b [x]
  (if (= 0 x) 0 (a (dec x))))

编译失败:

Unable to resolve symbol: b in this context

因为我没有定义b当我尝试调用它时a

例如,在红宝石中这很好用:

def a(x)
  x == 0 ? x : b(x-1)
end

def b(x)
  x == 0 ? x : a(x-1)
end
4

2 回答 2

7

任何一个:

(declare b)... ; 然后可以按原样使用您的其余代码

或者:

(def mutual
 (letfn [(a [ ... ] ...)
         (b [ ... ] ...)]
  [a b]))

(def a (first mutual))
(def b (second mutual))
于 2013-08-24T17:59:12.733 回答
6

根据代码的执行情况,请记住您可能会遇到堆栈溢出异常。

(clojure.core/trampoline)函数在哪里发挥作用并发挥其魔力。

trampoline 可用于转换需要相互递归而不消耗堆栈的算法。使用提供的参数调用 f(如果有)。如果 f 返回一个 fn,则不带参数调用该 fn,并继续重复,直到返回值不是 fn,然后返回该非 fn 值。请注意,如果您想将 fn 作为最终值返回,则必须将其包装在某种数据结构中,并在蹦床返回后将其解包。

于 2013-08-24T18:22:06.030 回答