Questo potrebbe da fare con gli obiettivi . L'idea stessa di un obiettivo è di essere in grado di ingrandire una particolare parte di una struttura immutabile e di essere in grado di 1) recuperare la parte più piccola da una struttura più grande, oppure 2) creare una nuova struttura più grande con una parte più piccola modificata . In questo caso, ciò che desideri è # 2.
In primo luogo, una semplice implementazione di Lens
, rubato this answer, rubato scalaz:
case class Lens[A,B](get: A => B, set: (A,B) => A) extends Function1[A,B] with Immutable {
def apply(whole: A): B = get(whole)
def updated(whole: A, part: B): A = set(whole, part) // like on immutable maps
def mod(a: A)(f: B => B) = set(a, f(this(a)))
def compose[C](that: Lens[C,A]) = Lens[C,B](
c => this(that(c)),
(c, b) => that.mod(c)(set(_, b))
)
def andThen[C](that: Lens[B,C]) = that compose this
}
successivo, un costruttore intelligente per creare una lente da "struttura più ampia" Map[A,B]
a "parte minore" Option[B]
. Indichiamo quale "parte più piccola" vogliamo vedere fornendo una chiave particolare. (Ispirato da quello che mi ricordo da Edward Kmett's presentation on Lenses in Scala):
def containsKey[A,B](k: A) = Lens[Map[A,B], Option[B]](
get = (m:Map[A,B]) => m.get(k),
set = (m:Map[A,B], opt: Option[B]) => opt match {
case None => m - k
case Some(v) => m + (k -> v)
}
)
Ora il codice si può scrivere:
val m2 = containsKey("Mark").mod(m)(_.map(_ - 50))
N.B. In realtà ho cambiato mod
dalla risposta che ho rubato in modo che tenga i suoi ingressi al curry. Questo aiuta ad evitare annotazioni di tipo extra. Nota anche _.map
, perché ricorda che il nostro obiettivo è da Map[A,B]
a Option[B]
. Ciò significa che la mappa rimarrà invariata se non contiene la chiave "Mark"
. Altrimenti, questa soluzione finisce per essere molto simile alla soluzione adjust
presentata da Travis.
Questo funziona solo se la chiave esiste nella mappa. Prendi in considerazione 'map.get (k) .fold (map) (b => map.aggiornato (k, f (b))) 'se vuoi ignorare una chiave mancante, o un approccio che ha' f: Option [B] => B' se vuoi essere in grado di impostare la chiave in sua assenza. – adamnfish
@adamnfish: regolare (m, "Mark") (_. GetOrElse (0) - 50) – mdenton8
Molto utile - Vorrei che 'adjust' fosse nella libreria standard! (probabilmente la variante fold di @adamnfish ..) –