两个函数以递归方式相互调用

spi*_*ike 6 clojure

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

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

(defn b [x]
  (if (= 0 x) 0 (a (dec x))))
Run Code Online (Sandbox Code Playgroud)

编译失败:

Unable to resolve symbol: b in this context
Run Code Online (Sandbox Code Playgroud)

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

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

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

def b(x)
  x == 0 ? x : a(x-1)
end
Run Code Online (Sandbox Code Playgroud)

noi*_*ith 6

之一:

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

要么:

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

(def a (first mutual))
(def b (second mutual))
Run Code Online (Sandbox Code Playgroud)


Chi*_*ron 6

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

有(clojure.core/trampoline)功能进入游戏并发挥其魔力.

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