2011-07-06 108 views
3

我試圖通過循環設置向量的每個元素等於3。我得到:無法通過元素循環元素更新向量

java.lang.ClassCastException:clojure.lang.PersistentVector可以 不能被轉換爲java.lang.Number中

這是代碼。

(def w [1 2 3]) 
(defn update [index value] 
    (assoc w index value)) 

(loop [i -1] 
    (if (< (count w) i) 
    w 
    (recur (update (+ i 1) 3)))) 

回答

3

您正在通過傳遞(更新...)到複合函數來混合整數和矢量類型。循環語句應該看起來像(loop [i -1 w w] ..),然後你可以將你的新的向量收集到本地的「w」中。如果你想使用recure聲明這個代碼可以幫助你(我想有很多其他的選項來改變一個向量的值):

(let [value 4 
     w [1 2 3]] 

    (loop [i 0 
     w w] 
    (if (< i (count w)) 
     (recur (inc i) (assoc w i value)) 
     w))) 
9

您的更新功能不工作,你所期望的方式。

(assoc w index value) 

產生一個新向量基於W,不同的是在索引元素是現在。它不改變w

user> (def w [1 2 3]) 
user> (assoc w 0 9) 
    [9 2 3] 
user> w 
    [1 2 3] 

此外,你沒有正確使用循環/重複。你開始循環,我綁定到-1,打算用它作爲w的索引,但重複調用循環不是與我的下一個值,而是通過更新返回w的更改副本。

嘗試更多的東西一樣:

(def w [1 2 3]) 
(loop [i 0, v w] 
    (if (< (count w) i) 
     v 
     (recur (inc i) (assoc v i 3)))) 

但是,因爲你沒有實際使用來計算元素的新值的索引,你可以使用地圖而不是循環。由於只是將每個元素設置爲一個常量而不考慮其舊值,因此可以不斷使用clojure的內置函數

(vec (map (constantly 3) w)) 

地圖返回一個序列,我已經把它包在一個調用VEC改造它放回載體。

+1

用於製作具有相同值的向量''(repeat(count w)3)''就足夠了,沒有'map' –

+0

好,是的,但那麼''3 3 3] ',但這可能與原來的問題相去甚遠,對我們有很大的幫助。 – bendin

2

您可以通過地圖和不斷這樣做:

(def w [1 2 3]) 

(map (constantly 3) w) 
=> (3 3 3) 

請注意,這不會改變W - 它返回三分球的新序列相同長度W上。因此,您同樣可以通過使用得到同樣的結果:

(repeat (count w) 3) 
=> 3 

如果實際上要換W,那麼我會建議作出W時原子,因此它可以與交換更新!功能:

(def w (atom [1 2 3])) 

(swap! w 
    (fn [old-w] 
    (vec (map (constantly 3) old-w)))) 

@w 
=> [3 3 3] 

最後,如果你真的想在一個時間來更新w的一種的元素,你可以這樣做:

(dotimes [i (count @w)] 
    (swap! w 
    (fn [previous-w] 
     (assoc previous-w i 3)))) 

這似乎相當unidiomatic和必要的Clojure中,但它做的工作.....