4

次のような関数があるとします。

user=> (def m {10 5, 5 2, 2 1})
#'user/m
user=> (defn hierarchy [x] (when x (cons x (hierarchy (get m x)))))
#'user/hierarchy
user=> (hierarchy 10)
(10 5 2 1)
user=> 

スタックの深さが小さいため、ここでは明らかにこれで問題ありません。しかし、私が返したいリストを作成しているこの一般的なタイプの問題では、再帰呼び出しは常にコンス呼び出し内で終了します。これを末尾再帰に変換して、再帰を使用し、スタック スペースを使用しないようにするにはどうすればよいでしょうか。

4

4 に答える 4

3

アキュムレータを読んでください。

Clojure では、この特定の問題は を使用して解決できますlazy-seqlazy-seq計算を延期するため、スタック オーバーフローは (通常) 問題になりません。

(defn hierarchy
  [x]
  (when x
    (lazy-seq
      (cons x (hierarchy (get m x))))))
于 2012-11-06T06:53:13.267 に答える
3

再帰を使用せずにこれをエレガントに解決できます。

(defn hierarchy [x]
  (take-while identity (iterate m x)))
于 2012-11-06T08:25:51.330 に答える
2

最初のバリアント

(defn hierarchy* [res x]
  (if-not x
    res
    (recur (conj res x) (get m x))))

(defn hierarchy [x]
  (hierarchy* [] x))

2位

(defn hierarchy [x]
  (loop [res []
         next-x x]
    (if-not next-x
      res
      (recur (conj res next-x) (get m next-x)))))
于 2012-11-06T07:14:45.580 に答える
1

追加lazy-seq:

(defn hierarchy [x] (when x (cons x (lazy-seq (hierarchy (get m x))))))
于 2012-11-06T06:59:25.710 に答える