clojure idiomatic

¿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.