Sto cercando di implementare un default valued map e mi piacerebbe filtri, mappe, ecc. Su un DefaultingMap
per produrre anche un DefaultingMap
quando possibile. Ecco la mia implementazione iniziale:Implementare una scala di scala in modo che la mappa, il filtro, ecc. Producano il tipo corretto
class DefaultingMap[K, V](defaultValue: => V)
extends mutable.HashMap[K, V]
with mutable.MapLike[K, V, DefaultingMap[K, V]] {
override def empty = new DefaultingMap[K, V](defaultValue)
override def default(key: K): V = {
val result = this.defaultValue
this(key) = result
result
}
}
ricevo oggetti di tipo DefaultingMap
quando uso filter
, ma non quando uso map
:
scala> val counter = new DefaultingMap[Char, Int](0)
counter: DefaultingMap[Char,Int] = Map()
scala> for (c <- "ababcbbb") counter(c) += 1
scala> counter.filter{case (k, v) => v > 1}
res1: DefaultingMap[Char,Int] = Map((a,2), (b,5))
scala> counter.map{case (k, v) => (k, v * 2)}
res2: scala.collection.mutable.HashMap[Char,Int] = Map((a,4), (c,2), (b,10))
La differenza tra questi due metodi sembra essere che map
prende un implicito CanBuildFrom
. Quindi ho capito che ho bisogno di avere unda qualche parte per fornire il CanBuildFrom
. La mia prima intuizione è stato quello di fare ciò che è fatto in HashMap:
object DefaultingMap extends generic.MutableMapFactory[DefaultingMap] {
def empty[K, V]: DefaultingMap[K, V] = // Not possible!
implicit def canBuildFrom[K, V]:
generic.CanBuildFrom[Coll, (K, V), DefaultingMap[K, V]] =
new MapCanBuildFrom[K, V]
}
Credo che questo sarebbe farlo per compilare, ma questo approccio non funziona perché è impossibile definire il metodo empty
- è necessario conoscere ciò che il defaultValue
dovrebbe essere. Se potessi definire lo CanBuildFrom
nella classe stessa, anziché l'oggetto associato, sarei a posto perché lo defaultValue
è disponibile lì.
Come posso farlo funzionare?
Il punto su MutableMaps che già è Builder è bello - questo semplifica il codice in alcuni punti. Per quanto riguarda l'applicazione senza parametri, sai quando viene richiamato? Forse se è raro non sono troppo preoccupato per questo. – Steve
BTW, penso che potrebbe essere più chiaro se hai abbandonato il metodo 'newBuilder' e hai appena creato la DefaultingMap direttamente. – Steve
Il parametro 'apply' viene richiamato in' breakOut', che è l'unico posto, per quanto ne so ... Vedi l'oggetto del pacchetto di raccolta. E hai ragione su 'newBuilder'. Tuttavia, lascerei comunque la definizione del metodo 'newBuilder' nel companion. Se la 'Mappa' avesse compagni che funzionassero allo stesso modo di' Seq', sarebbe poi diventato utile. Inoltre, li renderebbe conformi ai companion 'MapFactory' standard che hanno il' newBuilder'. – axel22