实现一个scala集合,以便map,filter等生成正确的类型
我正在尝试实现一个
default valued map,我想在DefaultingMap上使用过滤器,贴图等,以便尽可能生成DefaultingMap.这是我最初的实现:
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 } } 当我使用过滤器时,我得到了DefaultingMap类型的对象,但是当我使用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,4),(c,10)) 这两种方法之间的区别似乎是map采用隐式CanBuildFrom.所以我认为我需要在某处提供隐式def来提供CanBuildFrom.我的第一个直觉是在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),V]] = new MapCanBuildFrom[K,V] } 我相信这会让它编译,但这种方法不起作用,因为无法定义空方法 – 你需要知道defaultValue应该是什么.如果我可以在类本身中定义CanBuildFrom而不是伴随对象,我会没问题,因为defaultValue在那里可用. 我怎样才能让它发挥作用? 解决方法
可变映射是Scala中的构建器,因此默认情况下,MapFactory会使用相关类型的空映射来获取构建器.
如果您有自定义地图构建规则,您可以做的一件事就是定义类似于collection.generic.MapFactory的自定义工厂.您必须以类似的方式定义它,但同时使空方法和newBuilder方法为defaultValue采用另一个参数. 有些事情(如果您在建议的其他链接中阅读有关Scala 2.8集合API的更多信息,您会发现您不必为地图实现通用伴随对象): import collection._ class DefaultingMap[K,V](val defaultValue: V) extends mutable.HashMap[K,V] with mutable.MapLike[K,V]] { override def empty = new DefaultingMap(defaultValue) } object DefaultingMap { def newBuilder[K,V](d: V): DefaultingMap[K,V] = new DefaultingMap[K,V](d) implicit def canBuildFrom[K,V] = new generic.CanBuildFrom[DefaultingMap[K,V],V]] { def apply(from: DefaultingMap[K,V]) = newBuilder[K,V](from.defaultValue) def apply() = error("unsupported default apply") } } object Main { def main(args: Array[String]) { println((new DefaultingMap[Int,Int](5)).defaultValue) println(((new DefaultingMap[Int,Int](5)).map(x => x)).defaultValue) } } 打印: $scalac defaulting.scala $scala Main 5 5 我承认,这仍然没有解决无参数应用的问题. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |