Clojure 如何更新原子中的试剂向量

Clojure 如何更新原子中的试剂向量,clojure,clojurescript,reagent,Clojure,Clojurescript,Reagent,我有一个试剂原子: (defonce order (r/atom {:firstName "" :lastName "" :toppings [] })) 我想向:toppings向量添加浇头。我在以下方面尝试了许多变化: (swap!(:配料顺序)conj“Pepperoni”)这给了我:未捕获错误:没有协议方法是wap.-swap!为空类型定义: (swap!order:toppings“Pepperoni”)这是一种工作,但只是更新顺序,而不是:toppings向量。当我定义订单时,我只

我有一个试剂原子:

(defonce order (r/atom {:firstName "" :lastName "" :toppings [] }))
我想向
:toppings
向量添加浇头。我在以下方面尝试了许多变化:

(swap!(:配料顺序)conj“Pepperoni”)
这给了我:
未捕获错误:没有协议方法是wap.-swap!为空类型定义:

(swap!order:toppings“Pepperoni”)
这是一种工作,但只是更新顺序,而不是
:toppings
向量。当我定义订单时,我只得到最新的值


向my
:toppings
vector添加(和删除)值的正确方法是什么?

您可以使用以下内容更新toppings:

(swap! order update :toppings conj "Pepperoni")

我会把
配料
做成一套。我认为您不希望在该系列中使用重复的浇头,因此一套是合适的:

(defonce order (r/atom {:first-name "" :last-name "" :toppings #{}})) ; #{} instead of []
然后你仍然可以如另一个答案中所述:

(swap! order update :toppings conj "Pepperoni")
但你也可以:


再解释一下,当您执行
(swap!(:toppings order)
)时,您正在从
order
检索
:toppings
键,如果它是一个映射,但它是一个原子,那么这是有意义的,因此
(:toppings order)
返回
nil

swap的第一个参数应始终是原子(
试剂
原子的工作方式相同)。第二个参数应该是一个函数,它将原子的内容作为第一个参数。然后,您可以选择提供更多参数,这些参数将传递给函数参数

代替minhtuannguyen的答案,您可以执行以下操作:

(swap! order
  (fn a [m]
    (update m :toppings
      (fn b [t]
        (conj t "Pepperoni")))))
fn a
接收原子内部的映射,将其绑定到
m
,然后更新它并返回一个新映射,该映射成为原子的新值

如果愿意,可以重新定义
fn a
以获取第二个参数:

(swap! order
  (fn a [m the-key]
    (update m the-key
      (fn b [t]
        (conj t "Pepperoni"))))
  :toppings)
(swap! order update :toppings
  (fn b [t the-topping]
    (conj t the-topping))
  "Pepperoni"))
:toppings
现在作为第二个参数传递给
fn a
,然后传递给
fn a
内部的
update
。我们可以对
update
的第三个参数执行相同的操作:

(swap! order
  (fn a [m the-key the-fn]
    (update m the-key the-fn))
  :toppings
  (fn b [t]
    (conj t "Pepperoni")))
现在
update
fn a
具有相同的签名,因此我们不再需要
fn a
。我们可以直接提供
update
来代替
fn a

(swap! order update :toppings
  (fn b [t]
    (conj t "Pepperoni")))
但是我们可以继续,因为
update
还接受更多的参数,然后将这些参数传递给提供给它的函数。我们可以重写
fn b
来接受另一个参数:

(swap! order
  (fn a [m the-key]
    (update m the-key
      (fn b [t]
        (conj t "Pepperoni"))))
  :toppings)
(swap! order update :toppings
  (fn b [t the-topping]
    (conj t the-topping))
  "Pepperoni"))
再次说明,
conj
fn b
具有相同的签名,因此
fn b
是多余的,我们可以在其位置使用
conj

(swap! order update :toppings conj "Pepperoni")

因此,我们最终得到了minhtuannguyen的答案。

下面所有的答案都是有价值的。我接受了最直接回答这个问题的答案,但其他的答案提供了关于如何处理原子的更多见解。如果有人想把意大利香肠的量增加一倍怎么办?;-)@纳坦达维斯很公平。:)使用从顶部名称到数量的哈希映射。例如,
{“辣味香肠”2}
。增加
(按顺序更新[:toppings“pepperoni”]inc)
dec
减少。当值为0时,可能会删除一个条目。