在Clojure的地图上更改值的正确方法

时间:2019-03-06 22:04:33

标签: clojure

好吧,我是clojure的新手,这应该很容易,但是对于我一生来说,我找不到答案

假设我有这张地图

.env.example

现在我想将:a的值更改为5。我不知道如何正确执行此操作

我知道ui<-fluidPage( actionButton(inputId="model", label="Edit Model") ) server<-function(input, output, session) { rv<-reactiveValues(header="Standard Model") observeEvent(input$model, { showModal( modalDialog( fluidPage( fluidRow(h3(rv$header)), sliderInput(inputId="factor_1", "Factor #1", value=70, min=0, max=100), sliderInput(inputId="factor_2", "Factor #2", value=30, min=0, max=100) ), footer=modalButton("Save Weights"), size="s", easyClose=TRUE ) ) }) observe({if (!is.null(input$factor_1)) { if (input$factor_1!=70) { rv$header<-"Custom Model" } } }) } shinyApp(ui=ui, server=server) (def mymap {:a 10 :b 15}) 可以进行更改,但是它们都接受作为最后一个参数的函数,该函数适用于该值。我不想那样,我不想运行任何功能,我只想简单地将:a设置为5。

我认为我可以传递一个仅返回5并忽略arg的匿名函数,但这是正确的方法吗?对我来说不好看

update

2 个答案:

答案 0 :(得分:5)

assoc并不将函数作为最后一个参数。除非您想将功能与地图中的按键关联。 (assoc mymap :a 5)做您想要的。

我要补充一点,update是具有功能的 ,在与constantly或其他功能结合使用时也可以在这里使用(尽管没有在assoc上使用它的原因):

; constantly returns a function that throws away any arguments given to it,
; and "constantly" returns the given value
(update mymap :a (constantly 5))

; Basically the same as above
(update mymap :a (fn [_] 5))

答案 1 :(得分:0)

请记住,由于mymap是不可变的,因此调用(update mymap :a (constantly 5))(assoc mymap :a 5)将返回映射{:a 5 :b 15},对mymap的进一步引用将继续返回{{ 1}}。

如果您想为以后的调用更新值,可以考虑使用原子。

{:a 10 :b 15}

只要确保要引用原子的值,请使用@符号将其取消引用。例如:(defonce mymap (atom {:a 10 :b 15})) (defn change-mymap [value] (swap! mymap #(assoc % :a value)))

当您调用(clojure.pprint/pprint @mymap)时,这将更新存储的mymap值以将(change-mymap 5)设置为新值,而仅将映射中的任何其他键值对保留。当您响应其他系统的输入时,在客户端/服务器代码中以更新状态进行映射时,这将很有帮助。

还请注意,对于嵌套地图,例如

:a

您可以通过路径向量在地图中找到特定值。您可以使用(defonce nested (atom {:a "a value" :b {:inner "Another value" :count 3 :another {:value 5}}})) 函数来检索值get-in 并且您可以将(get-in @nested [:b :another :value])assoc-in与路径一起使用以更新值。这也允许您扩展地图。例如,使用上述嵌套值,可以将整个部分添加到树中: update-in 将更新初始地图,如下所示:

(swap! nested #(assoc-in % [:a :b :c :d] "foo"))