2012-08-17 8 views
6

Teniendo en cuenta la situación siguiente:¿Cómo actualizar los registros en un mapa de ref en Clojure?

(defrecord Person [firstname lastname]) 
(def some-map (ref {})) 

(dosync 
    (alter some-map conj {1 (Person. "john" "doe")}) 
    (alter some-map conj {2 (Person. "jane" "jameson")})) 

Para cambiar el apellido de "Joe" a "nick", hago lo siguiente:

(dosync 
    (alter some-map (fn [m]     
        (assoc m 1 
         (assoc (m 1) :firstname "nick"))))) 

Cuál es la forma idiomática de hacer esto en Clojure?

Respuesta

5

No es necesario utilizar la actualización, para este caso, assoc-in es exactamente lo que desea.

(dosync (alter some-map assoc-in [1 :firstname] "nick"))

+0

De acuerdo, la actualización es demasiado general en este caso. –

2

Editar: Para su ejemplo assoc-in es mejor, ya que ignora el valor anterior. Mantener esta respuesta para los casos en que realmente necesita el valor anterior:

El update-in está ahí para actualizar las estructuras anidadas:

(alter some-map update-in [1 :firstname] (constantly "nick")) 

El último argumento es una función del valor de ser "sustituido" (como assoc , no reemplaza sino que devuelve una nueva estructura.) En este caso, se ignora el valor anterior, de ahí la función constantly que siempre devuelve "nick".

+0

se puede dejar de lado la envoltura función anónima: '(modificar algunas de ruta de actualización en [1: Nombre] (constante "nick"))' –

+0

@JoostDiepenmaat Gracias, siempre me olvido de la opcional argumentos para funciones de orden superior en Clojure, se editarán. –

+0

Acepté la otra respuesta, pero gracias por su sugerencia. No lo sabía constantemente; ahora entiendo por qué mis otros intentos fallaron. – Odinodin

Cuestiones relacionadas