2014-01-23 108 views
5

我在基於Eratosthenes Sie的Clojure中編寫了一個Sieve類型的函數,並且遇到了一對列表錯誤:ClassCastException clojure.lang.Cons無法轉換爲java.lang.Number中  clojure.lang.Numbers.remainder(Numbers.java:171)在Clojure中使用cons的對集合


(defn mark-true [n] 
    (cons n '(true))) 

(defn unmarked? [ns] 
    (not (list? ns))) 

(defn divides? [m n] 
    (if (= (mod n m) 0) 
     true 
     false)) 

(defn mark-divisors [n ns] 
    (cond 
     (empty? ns) '() 
     (and (unmarked? (first ns)) (divides? n (first ns))) 
      (cons (cons (first ns) '(false)) (mark-divisors n (rest ns))) 
     :else (cons (first ns) (mark-divisors n (rest ns))))) 

(defn eratosthenes [ns] 
    (cond 
     (empty? ns) '() 
     (unmarked? (first ns)) 
      (cons (mark-true (first ns)) 
       (eratosthenes (mark-divisors (first ns) (rest ns)))) 
     :else (cons (first ns) (eratosthenes (rest ns))))) 

;(eratosthenes (list 2 3 4 5 6)) 
;=> ClassCastException clojure.lang.Cons cannot be cast to java.lang.Number  clojure.lang.Numbers.remainder (Numbers.java:171) 

但是,更改標誌風格,在利弊放棄使用連詞或向量對,而不是兩個solv編輯錯誤。

不過我找了錯誤的一個很好的解釋....

+1

你不能指望一個答案,如果你不發佈所有相關的代碼。在那裏沒有剩餘的電話......明顯的「標記除數」缺失。 –

+0

你是對的 - 泰克 – FredAKA

+0

在某些點分歧?函數接收3和(4 false)參數。第二個參數不能轉換爲數字 – edbond

回答

6

的問題是,list?檢查與cons內置序列失敗,如下面所示:

(list? (conj() 1)) ;=> true 
(list? (cons 1())) ; => false 

你可以切換您致電list?致電seq?,它應該有效。

要詳細瞭解這是爲什麼,所以我建議你閱讀這個答案:Clojure: cons(seq) vs. conj(list)

+0

太好了。感謝解決方案。有趣的清單?在閱讀參考文獻時沒有討論。你的例子應該是一個包含在那裏和http://clojuredocs.org/clojure_core/clojure.core/list_q – FredAKA

+0

我認爲是設計有錯誤(list?(cons 1())); => false – FredAKA

+0

@FredAKA,你需要考慮到Clojure中的列表和seq之間存在區別。 – ponzao