Estoy tratando de implementar un default valued map, y me gustaría filtros, mapas, etc. durante un DefaultingMap
que también producen una DefaultingMap
siempre que sea posible. Aquí está mi aplicación inicial:Implementar una colección Scala de manera que un mapa, filtro, etc. producir el tipo correcto
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
}
}
consigo objetos de tipo DefaultingMap
cuando uso filter
, pero no cuando se utiliza 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 diferencia entre estos dos métodos parece ser que map
toma una implícito CanBuildFrom
. Así que deduzco que necesito tener un implicit def
en algún lugar para proporcionar el CanBuildFrom
. Mi primera intuición era hacer lo que se hace en 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]
}
Creo que esto sería que se compile, pero este método no funcionará porque es imposible definir el método empty
- lo que necesita saber lo que el defaultValue
debiera ser. Si pudiera definir el CanBuildFrom
en la clase misma, en lugar del objeto complementario, estaría bien porque el defaultValue
está disponible allí.
¿Cómo puedo hacer que funcione?
El punto de que MutableMaps ya es Builders es bueno, eso simplifica el código en algunos lugares. En cuanto a la aplicación sin parámetros, ¿sabes cuándo se invoca? Quizás si no es común no estoy demasiado preocupado por eso. – Steve
Por cierto, creo que podría ser más claro si se descarta el método 'newBuilder' y acaba de crear el DefaultingMap directamente. – Steve
Parameterless 'apply' se invoca en' breakOut', que es el único lugar, que yo sepa ... Vea el objeto del paquete de recopilación. Y tienes razón sobre 'newBuilder'. Sin embargo, aún dejaría la definición del método 'newBuilder' en el acompañante. Si el 'Mapa' tuviera compañeros que funcionaran de la misma manera que' Seq's, entonces sería útil. Además, los haría compatibles con los compañeros estándar de 'MapFactory' que tienen el' newBuilder'. – axel22