¿Cuál es la forma idiomática de asociar varias claves/valores en un mapa anidado en Clojure?
idiomatic (1)
Imagina que tienes un mapa como este:
(def person {
:name {
:first-name "John"
:middle-name "Michael"
:last-name "Smith" }})
¿Cuál es la forma idiomática de cambiar los valores asociados con: primer nombre y: apellido en una expresión?
(Aclaración: digamos que desea establecer: primer nombre a "Bob" y: apellido a "Doe". También digamos que este mapa tiene otros valores que queremos preservar, por lo que construirlo desde cero no es una opinión)
Aquí hay un par de maneras.
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"}}
Editar
update-in
hace una assoc
recursiva en su mapa. En este caso es aproximadamente equivalente a:
user> (assoc person :name
(assoc (:name person)
:first-name "Bob"
:last-name "Doe"))
La repetición de las teclas se vuelve cada vez más tediosa a medida que profundiza en una serie de mapas anidados. la recursión de update-in
permite evitar la repetición de teclas (por ejemplo, :name
) una y otra vez; los resultados intermedios se almacenan en la pila entre llamadas recursivas. Eche un vistazo a la fuente de update-in para ver cómo se hace.
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
es dinámico (como lo son update-in
, assoc-in
y la mayoría de las otras funciones de Clojure que operan en estructuras de datos de Clojure). Si assoc
en un mapa, devuelve un mapa. Si se assoc
a un vector, devuelve un vector. Mire la fuente de assoc y eche un vistazo en RT.java
en la fuente de Clojure para obtener más información.