在clojure中同时更新两个值
我想知道如何同时更新两个值。例如,我想在增加月份的同时减少年龄。我的代码是在clojure中同时更新两个值,clojure,update-in,Clojure,Update In,我想知道如何同时更新两个值。例如,我想在增加月份的同时减少年龄。我的代码是 user=>(def users {:month 1 :age 26}) user=>(update-in users [:month :age] inc dec) 我知道这个语法是不正确的,但是我怎样才能解决这个问题呢?我需要同时更新。因为如果我先更新月份,然后更新年龄,那么当我更新第二个地图时,第一个地图将丢失。或者有其他方法解决这个问题吗?更新不修改值,它只返回一个新值,所以它只是一个函数。如果需要更
user=>(def users {:month 1 :age 26})
user=>(update-in users [:month :age] inc dec)
我知道这个语法是不正确的,但是我怎样才能解决这个问题呢?我需要同时更新。因为如果我先更新月份,然后更新年龄,那么当我更新第二个地图时,第一个地图将丢失。或者有其他方法解决这个问题吗?
更新不修改值,它只返回一个新值,所以它只是一个函数。如果需要更新地图的两个字段,最简单的方法就是调用update
两次,首先在原始地图上,然后在第一次更新的结果上:
(defn update-month-and-age [user]
(update (update user :month inc) :age dec))
使用->
哪个看起来更好:
(defn update-month-and-age [user]
(-> user
(update :month inc)
(update :age dec)))
update
不修改值,它只返回一个新值,因此它只是一个函数。如果需要更新地图的两个字段,最简单的方法就是调用update
两次,首先在原始地图上,然后在第一次更新的结果上:
(defn update-month-and-age [user]
(update (update user :month inc) :age dec))
使用->
哪个看起来更好:
(defn update-month-and-age [user]
(-> user
(update :month inc)
(update :age dec)))
在这种简单的情况下(更新函数而不增加参数),您也可以这样做:
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)}
如果使用其他参数,则会更加详细:
user> (reduce-kv (partial apply update)
users
{:month [+ 2] :age [dec] :records [conj 101]})
{:month 3, :age 25, :records [1 2 3 101]}
嗯,这比简单使用线程宏更糟糕。在这种简单的情况下(更新函数而不增加参数),您也可以这样做:
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)}
如果使用其他参数,则会更加详细:
user> (reduce-kv (partial apply update)
users
{:month [+ 2] :age [dec] :records [conj 101]})
{:month 3, :age 25, :records [1 2 3 101]}
嗯,这比简单使用线程宏更糟糕。我试图通过编写一个函数来解决这个问题,该函数采用map:keyword->function,并生成一个将所有函数应用于相关记录/映射条目的函数
这样的功能是
(defn field-updater [fn-map]
(fn [record]
(reduce
(fn [m [k f]] (assoc m k (f (m k))))
record
fn-map)))
我们使用它来生成所需的字段更新程序:
(def update-in-users (field-updater {:month inc :age dec}))
。。。然后我们可以申请
(update-in-users users)
;{:month 2, :age 25}
我试图通过编写一个函数来解决这个问题,该函数采用map:keyword->function,并生成一个将所有函数应用于相关记录/映射条目的函数
这样的功能是
(defn field-updater [fn-map]
(fn [record]
(reduce
(fn [m [k f]] (assoc m k (f (m k))))
record
fn-map)))
我们使用它来生成所需的字段更新程序:
(def update-in-users (field-updater {:month inc :age dec}))
。。。然后我们可以申请
(update-in-users users)
;{:month 2, :age 25}
我同意你的第一个解决方案,它确实有效。但是对于第二个,我知道你想告诉我使用箭头符号更好,但是这个方法不适用于这个问题。因为在更新第二个更新时不会保存第一个更新。第一种方法的结果是{:month 2:age 25}
。但是第二个结果是{:month 1:age 25}
。谢谢你的帮助@秀芬许不,那不对(更新月份和年龄{:month 1:age 26})
返回两种实现的{:month 2:age 25}
。用户>(macroexpand-1'(->用户(更新:month inc)(更新:age dec))=>(更新(更新用户:month inc):age dec)
@Elogent非常感谢!这是我的错,当我使用你的代码时,我写了一些错误。谢谢lot@ArthurUlfeldt非常感谢你!您的宏扩展非常清晰,我更容易理解。我同意您的第一个解决方案,它确实有效。但是对于第二个,我知道你想告诉我使用箭头符号更好,但是这个方法不适用于这个问题。因为在更新第二个更新时不会保存第一个更新。第一种方法的结果是{:month 2:age 25}
。但是第二个结果是{:month 1:age 25}
。谢谢你的帮助@秀芬许不,那不对(更新月份和年龄{:month 1:age 26})
返回两种实现的{:month 2:age 25}
。用户>(macroexpand-1'(->用户(更新:month inc)(更新:age dec))=>(更新(更新用户:month inc):age dec)
@Elogent非常感谢!这是我的错,当我使用你的代码时,我写了一些错误。谢谢lot@ArthurUlfeldt非常感谢你!你的宏扩展非常清晰,我更容易理解。嗨,利奥!实际上,它应该是原子的,但我不认为有必要使用ref和dosync来解决这个问题。非常感谢你!因为clojure数据结构是不可变的,所以在这两个调用之间完全不可能更改数据。在Clojure中,对不可变集合的任何操作序列都是原子的!实际上,它应该是原子的,但我不认为有必要使用ref和dosync来解决这个问题。非常感谢你!因为clojure数据结构是不可变的,所以在这两个调用之间完全不可能更改数据。在Clojure中,对不可变集合的任何操作序列都是原子的。