2016-03-29 40 views
0

我想重寫(我不知道如果原來的實現是懶惰的不是)一個懶惰實現的Clojure的使用lazy-seq的作品像這樣交錯的:懶重新實現Clojure的交織

(take 4 (lazy-interleave ’(1 2 3) ’(a b c))) 
(1 a 2 b) 

我想出了這樣的事情,但我不知道爲什麼它不工作:

(defn lazy-interleave [v1 v2] 
    (lazy-seq (concat (list (first v1) (first v2))) (lazy-interleave (next v1) (next v2))) 
    ) 

編輯:

個多虧了亞瑟的答案,這裏是修改過的工作方案:

(defn lazy-interleave [v1 v2] 
    (lazy-seq 
     (cons (first v1) (cons (first v2) (lazy-interleave (rest v1) (rest v2)))) 
    ) 
    ) 

回答

3

格式化的位揭示了問題:

(defn lazy-interleave [v1 v2] 
    (lazy-seq 
    (concat (list (first v1) (first v2))) 
    (lazy-interleave (next v1) (next v2)))) 

換句話說,你構建的是,當實現一個懶序列,將評估(concat (list (first v1) (first v2))),忽略結果,然後嘗試評估並返回(lazy-interleave (next v1) (next v2))。對lazy-interleave的這個呼叫也做了同樣的事情,再次丟棄了v1v2等等的第一個元素,並且無限次地。

因爲沒有空檢查,所以你永遠不會到達最低點,所以(next nil)返回nil,即使在耗盡兩個序列之後它也會繼續運行。您沒有得到StackOverflowError,因爲您使用的是惰性序列而不是遞歸。

正確實現的應該是這樣的:

(defn lazy-interleave [v1 v2] 
    (when (and (seq v1) (seq v2)) 
    (lazy-cat [(first v1) (first v2)] 
       (lazy-interleave (rest v1) (rest v2))))) 
+0

謝謝,我不知道有一個'懶貓'。只有一個問題:即使沒有用懶惰貓檢查,我們也可以從「lazy-interleave」中獲取有限數量的元素,但爲什麼我們不能用lazy-seq來做呢?在你的例子中,我會爲'(取2(lazy-interleave [1] []))'得到'(1 nil)',但即使使用'take'我的代碼也不起作用 – Yar

+2

作爲一個喜歡貓的程序員,我試圖使用該功能,只要它可以適合 –

+0

@ArthurUlfeldt哈哈完全明白了。再次感謝。 – Yar

1

interleave已經是懶惰:

user> (interleave (take 5 (iterate #(do (println "sequence A:" %) (inc %)) 0)) 
        (take 5 (iterate #(do (println "sequence B:" %) (inc %)) 100))) 
sequence A: 0 
sequence B: 100 
sequence A: 1 
sequence B: 101 
sequence A: 2 
sequence B: 102 
sequence A: 3 
sequence B: 103 
(0 100 1 101 2 102 3 103 4 104) 


user> (take 4 (interleave (take 5 (iterate #(do (println "sequence A:" %) (inc %)) 0)) 
          (take 5 (iterate #(do (println "sequence B:" %) (inc %)) 100)))) 
sequence A: 0 
sequence B: 100 
(0 100 1 101) 

而且它的核心的實現看起來很像你的例子:

(lazy-seq 
     (let [s1 (seq c1) s2 (seq c2)] 
     (when (and s1 s2) 
      (cons (first s1) (cons (first s2) 
           (interleave (rest s1) (rest s2))))))) 

除了它也可以在兩個以上的序列上工作,所以它還有另一個元素這種情況。