简体   繁体   English

在Clojure中同时更新两个值

[英]update two value at the same time in clojure

I am wondering how to update two values at the same time. 我想知道如何同时更新两个值。 For instance, I want to increase month and decrease age at the same time. 例如,我想同时增加月份并降低年龄。 My code is 我的代码是

user=>(def users {:month 1 :age 26})
user=>(update-in users [:month :age] inc dec)

I know this syntax is not correct, but how can I fix this? 我知道此语法不正确,但是如何解决呢? And I need to update at the same time. 而且我需要同时更新。 Since if I update month first and then update age, then the first map will lost when I update the second map. 由于如果我先更新月份然后更新年龄,那么当我更新第二张地图时,第一张地图将丢失。 Or is there other way to figure out this problem? 还是有其他方法可以解决这个问题?

update does not modify a value, it just returns a new value, so it's just a function. update不会修改值,它只会返回一个新值,因此它只是一个函数。 If you need to update 2 fields of a map, the straightforward way to do that is just call update twice, first on the original map and then on the result of the first update: 如果您需要更新地图的2个字段,则直接进行此操作的直接方法是两次调用update ,首先在原始地图上,然后在第一次更新的结果上:

(defn update-month-and-age [user]
  (update (update user :month inc) :age dec))

Which looks nicer using -> : 使用->看起来更好

(defn update-month-and-age [user]
  (-> user
      (update :month inc)
      (update :age dec)))

in this simple case (update functions without additional params) you could also do it like this: 在这种简单的情况下(没有附加参数的更新功能),您也可以这样做:

user> (def users {:month 1 :age 26 :records [1 2 3]})
#'user/users

user> (reduce-kv update users {:month inc :age dec :records reverse})
{:month 2, :age 25, :records (3 2 1)}

with additional params it would be a little bit more verbose: 再加上其他参数,将会更加冗长:

user> (reduce-kv (partial apply update)
                 users
                 {:month [+ 2] :age [dec] :records [conj 101]})
{:month 3, :age 25, :records [1 2 3 101]}

well, it is still worse then simple usage of threading macro. 好吧,比简单使用线程宏还要糟糕。

I'm tempted to solve this problem generally, by writing a function that takes a map: keyword -> function, and turns out a function that applies all the functions to the relevant record/map entries. 我很想通过编写一个采用map:keyword-> function的函数来解决这个问题,结果是将所有函数应用于相关记录/地图条目的函数。

Such a function is 这样的功能是

(defn field-updater [fn-map]
  (fn [record]
    (reduce
     (fn [m [k f]] (assoc m k (f (m k))))
     record
     fn-map)))

And we use it to generate your required field updater: 我们使用它来生成您所需的字段更新程序:

(def update-in-users (field-updater {:month inc :age dec}))

... which we can then apply ...然后我们可以申请

(update-in-users users)
;{:month 2, :age 25}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM