2016-11-10 80 views
1

我正在處理clojure中的遞歸,我並不真正瞭解它。 我從here做了一個小程序,試圖找到從1到20的所有數字可以分開的小數字。這是我編寫的代碼,但是肯定會有一些遺漏,因爲它不起作用。 你能幫我一下嗎?謝謝!clojure中的函數遞歸

(defn smallest [nume index] 
(while(not (= index 0)) 
    (do 
     (cond 
      (zero?(mod nume index))(let [dec' index] (smallest nume index)) 
      :else (let [inc' nume] (smallest nume index)))))) 

編輯: 看起來是更好的loop/recur,所以我試了一下:

(loop [nume 20 
      index 20] 
     (if (= index 0) 
     (println nume) 
     (if (zero?(mod nume index)) 
       (recur nume (dec index)) 
       (recur (inc nume) 20))))) 

工作。如果您對結果感到好奇 - > 232792560

+0

投資於理解循環/復發,不變性和標準庫系列變換功能 - 'while'是勢在必行的循環結構這在我的經驗,一個從來沒有使用超過一年一次或兩次以上。 –

+0

看來你是在黑暗中拍攝..例如,你認爲'(索引20)'做了什麼?而且,在「復發」中,價值的順序很重要,我不確定你是否按照自己的想法去做。 – Shlomi

+0

我剛剛編輯了關於訂單的問題。我的意思是(索引20)'是將索引再次設置爲20。 @shlomi – Capie

回答

1

while不會做您認爲的事。

在clojure中,一切(好,差不多)都是不可變的,這意味着如果index爲0,它在相同的上下文中將始終爲0。因此,循環直到1是沒有意義的。

有很多方法可以幫助您理解loop/recur,您可以通過多種方式實現您想要做的,第一個,也是最簡單的(我認爲!)給新手。因此,例如:

(loop [counter 0] 
    (when (< counter 10) 
    (println counter) 
    (recur (inc counter)))) 

在這裏,counter被定義爲0,它永遠不會改變以通常的方式。當你打recur,你提交一個新的價值,在這種情況下,增量以前counter的,進入一個全新的循環開始在loop,只是現在counter將被綁定到1

編輯:但是通知,該示例將始終返回nil。它僅用於println的副作用。爲什麼它會返回nil?因爲在最後一次迭代中,when子句將返回nil。如果您想返回其他內容,則應該使用if並指定您希望在最後一次迭代中返回的內容。

你應該多讀一點這個範例,也許可以像4clojure這樣的練習來更好地掌握這個。一旦你這樣做了,以這種方式思考就會變得簡單多了,這種風格的巨大好處將會開始顯現。

祝你好運!

0

這裏是一個強力實施測試,如果他們可以通過所有號碼從1分至10條件的所有數字代碼(請注意(範圍111)):

(first 
    (filter #(second %) 
      (map (fn[x] [x (every? identity 
            (map #(= 0 (mod x %)) 
            (range 2 11)))]) 
       (range 1 Integer/MAX_VALUE)))) 

它的輸出

[2520 true] 

不幸的是,對於更大的數字,這不是一個好方法。有了(範圍1 21),它在等待我的Macbook幾分鐘後才能完成。讓我們試試這個:

user=> (defn gcd [a b] (if (zero? b) a (recur b (mod a b)))) 
#'user/gcd 
user=> (reduce (fn[acc n] (if (not= 0 (mod acc n)) (* acc (/ n (gcd n acc))) acc)) 1 (range 1 11)) 
2520  
user=> (reduce (fn[acc n] (if (not= 0 (mod acc n)) (* acc (/ n (gcd n acc))) acc)) 1 (range 1 21)) 
232792560 
+1

「#(秒%)」與簡單的「秒」相同:) – Shlomi