不能通过逐个元素循环来更新vector



我试图通过循环设置向量的每个元素等于3。我:

. lang。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))))

你的update函数没有按你期望的方式工作。

(assoc w index value)

产生一个基于w的向量,只是索引处的元素现在是。It 不改变w

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

还有,你没有正确地使用循环/循环。在循环开始时,将i绑定到-1,打算将其用作w的索引,但是循环调用循环时,不是使用i的下一个值,而是使用update返回的w的修改副本。

试试这样写:

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

但是,由于实际上没有使用索引来计算元素的新值,因此可以使用map来代替loop。由于只需将每个元素设置为常量而不考虑其旧值,因此可以使用clojure的内置函数不断地

(vec (map (constantly 3) w))

Map返回一个序列,我已经将它包装在一个调用vec将其转换回一个向量中。

通过传递(update…)到递归函数,您正在混合整数和向量类型。循环语句应该看起来像(loop [i -1 w w] ..),然后你可以收集你的新向量到本地的"w"。如果你想使用正则语句,这段代码可以帮助你(我猜有很多其他选项来改变向量的值):

(let [value 4
      w [1 2 3]]
  (loop [i  0
         w  w]
    (if (< i (count w))
      (recur (inc i) (assoc w i value))
      w)))

您可以使用map和constant:

(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))))

这在Clojure中似乎相当统一和必要,但它确实有效.....

最新更新