Вот несколько способов.
user> (update-in person [:name] assoc :first-name "Bob" :last-name "Doe")
{:name {:middle-name "Michael", :last-name "Doe", :first-name "Bob"}}
user> (update-in person [:name] merge {:first-name "Bob" :last-name "Doe"})
{:name {:middle-name "Michael", :last-name "Doe", :first-name "Bob"}}
user> (update-in person [:name] into {:first-name "Bob" :last-name "Doe"})
{:name {:middle-name "Michael", :last-name "Doe", :first-name "Bob"}}
user> (-> person
(assoc-in [:name :first-name] "Bob")
(assoc-in [:name :last-name] "Doe"))
{:name {:middle-name "Michael", :last-name "Doe", :first-name "Bob"}}
Редактировать
update-in
делает рекурсивные assoc
s на вашей карте.В этом случае это примерно эквивалентно:
user> (assoc person :name
(assoc (:name person)
:first-name "Bob"
:last-name "Doe"))
Повторение ключей становится все более и более утомительным, когда вы углубляетесь в серию вложенных карт.update-in
рекурсия позволяет вам избегать повторения клавиш (например, :name
) снова и снова;промежуточные результаты хранятся в стеке между рекурсивными вызовами.Посмотрите на источник для update-in , чтобы увидеть, как это делается.
user> (def foo {:bar {:baz {:quux 123}}})
#'user/foo
user> (assoc foo :bar
(assoc (:bar foo) :baz
(assoc (:baz (:bar foo)) :quux
(inc (:quux (:baz (:bar foo)))))))
{:bar {:baz {:quux 124}}}
user> (update-in foo [:bar :baz :quux] inc)
{:bar {:baz {:quux 124}}}
assoc
является динамическим (как и update-in
, assoc-in
и большинство другихФункции Clojure, которые работают с структурами данных Clojure).Если assoc
на карту, он возвращает карту.Если вы assoc
на вектор, он возвращает вектор.Посмотрите на источник для assoc и посмотрите в RT.java
в источнике Clojure для деталей.