7

相互に再帰的に呼び出す 2 つの関数を 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) 関数が登場し、その魔法を実行する場所があります。

トランポリンを使用して、スタックを消費せずに相互再帰を必要とするアルゴリズムを変換できます。提供された引数があれば、それを指定して f を呼び出します。f が fn を返す場合、引数なしでその fn を呼び出し、戻り値が fn でなくなるまで繰り返し続け、その非 fn 値を返します。fn を最終値として返したい場合は、トランポリンが戻った後にデータ構造でラップし、アンパックする必要があることに注意してください。

于 2013-08-24T18:22:06.030 に答える