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时,可能会删除一个条目。