2011-07-06 125 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中,但它做的工作.....