我只是Clojure的初學者,我一直在嘗試4clojure.com問題。在那裏我偶然發現了一個問題,在這個練習中我應該寫一個flatten
的實現。Clojure:通過fn名稱的遞歸與遞歸
我基本上理解的尾調用優化的概念,以及如何recur
允許不消耗堆棧,而不是「正常」遞歸(我不知道是否有一個適當的期限)。
這就是爲什麼我不明白這是怎麼回事:
(defn foo1 [x]
(if (> x 0)
(do (println x)
(foo1 (dec x)))))
(defn foo2 [x]
(if (> x 0)
(do (println x)
(recur (dec x)))))
正如預期的那樣既foo1
和foo2
在功能上是相同的,但考慮(在我的情況100000)參數足夠大,我得到一個堆棧溢出™ foo1
而foo2
正常完成。
現在,到flatten
問題:
(defn flatten1 [ls]
(mapcat
#(if (coll? %)
(flatten1 %)
(list %))
ls))
(defn flatten2 [ls]
(mapcat
#(if (coll? %)
(recur %)
(list %))
ls))
測試用例:
(flatten [1 [2] 3 [4 [5 6 [7] 8]]])
(flatten1 [1 [2] 3 [4 [5 6 [7] 8]]])
(flatten2 [1 [2] 3 [4 [5 6 [7] 8]]])
預期結果:'(1 2 3 4 5 6 7 8)
好,flatten1
工程確定(這是一個很小的輸入反正)。但flatten2
只是無限期地掛起。 recur
不是針對在defn
處設置的遞歸點嗎?用名字遞歸到函數有什麼區別(優化放在一邊)?
很好,感謝您的解釋 – alepeino
爲了解決這個問題,有一個建議,雖然暫時休眠,但能夠啓用[recur to named loops](http://dev.clojure.org/display/design/Named+循環+與+復發到)。 – Thumbnail