2011-09-14 225 views
6

據我所知,在Clojure中遞歸而不使用循環.. recur語法對於短序列可能不是問題。但是,使用循環.. recur語法是編寫遞歸函數的首選方法。所以,我想從首選的方法開始。轉換爲循環...遞歸遞歸

然而,我一直在努力這個函數轉換[編輯],它返回序列的骨架(序列結構,而沒有它的值)

(defn skl 
    [tree] 
    (map skl (filter seq? tree))) 

與此數據測試

(def test_data1 '(1 (2 3) () (()) :a)) 
(def test_data2 '(1 2 (3 4) (5 (6 7 8)))) 

循環..重複語法。任何想法或指針的例子將不勝感激。

回答

3

您可能想要查看允許進行良好結構化樹編輯的拉鍊庫,儘管它可能不如您的原始版更優雅。我幾乎從不需要使用循環...反覆。幾乎總是有一個更高階的函數,以相同或更好的效率更優雅地解決問題。

替換maploop ... recur使代碼更加冗長和不太清晰。你也失去了分塊序列的好處。

+0

謝謝。你指的是Clojure.zip,對吧?我知道它,會使用它,並希望沒有這個練習。 – octopusgrabbus

+0

除了loop-recur,蹦牀也是一個有趣的功能,儘管在這裏並不直接適用。 –

4

循環和重複是一個簡單迭代的轉換。然而,下降到樹中本質上是遞歸的。您將不得不手動維護堆棧以將其轉換爲單個迭代。因此,您的代碼沒有「簡單」轉換。

+0

謝謝。我知道Clojure.zip,但想通過滾動我自己來嘗試提取骨架。這個例子來自UPenn的一些研究生計算機科學練習。你的回答至少告訴我這不是一個簡單的問題要解決。謝謝。 – octopusgrabbus

1

看看clojure.walk源代碼。它是一個對所有Clojure嵌套數據結構(不包括有序地圖)進行(批量)操作的庫。這裏有一些非常強大但看似簡單的代碼,通過本地定義的匿名函數使用遞歸而不使用循環/循環。

那裏的大多數功能都是基於步行道和prewalk功能,而這些功能又都是基於漫遊功能。通過源代碼和(prewalk-demo表單)和(postwalk-demo表單),您可以深入瞭解所採取的遞歸步驟。

我不知道這是否可以幫助你解決你的問題。我正在嘗試在同一個問題域中做一些事情:創建一個函數,將嵌套的映射和向量「扁平化」爲從根到葉的所有路徑的序列,每個路徑的一系列鍵和/或索引以'葉'價值。

這個庫似乎在整個結構中遞歸編輯值非常簡單。然而,我仍然不知道如何使用它來在功能上跟蹤我的'路徑'所需的迭代之間的累積數據,並且可能還有'骨架'問題。