以下代码:
var m: Map[String, Int] = Map("A" -> 1, "BB" -> 2, "CCC" -> 3)
m = m filterKeys { s => s.length < 3 }
不编译。我收到以下错误:
错误:类型不匹配
发现:collection.this.Map.Projection [scala.this.Predef.String,scala.this.Int]
required:collection.this.Map [scala.this.Predef.String,scala.this.Int]
m = m filterKeys {s =&gt; s.length&lt; 3}
我并不理解这一点,因为根据scaladoc Projection[A,B]
扩展了特性 Map[A,B+]
。也就是说,投影是地图。
我认为它可能与逆变类型B
有关但如果我使用Any
而不是Int
,它仍然无法编译。我错过了什么?解决方案是:
var m: Map[String, Int] = Map("A" -> 1, "BB" -> 2, "CCC" -> 3)
m = Map(m filterKeys { s => s.length < 3 } toSeq : _ *)
但这对我来说似乎不优雅。
答案 0 :(得分:0)
好的 - 这已经在scala控制台的帮助下找到了:
scala> var m = Map("A" -> 1, "BB" -> 2, "CCC" -> 3)
m: scala.collection.immutable.Map[java.lang.String,Int] = Map(A -> 1, BB -> 2, CCC -> 3)
因此类型推断将m的类型推断为不可变映射。以下代码将编译好:
var m: collection.Map[String, Int] = Map("A" -> 1, "BB" -> 2, "CCC" -> 3)
m = m filterKeys { s => s.length < 3 }
但是,由于无法以返回collection.Map
的方式添加地图,因此这没有多大帮助。我认为他们应该覆盖从++
继承的Iterable
方法,并将Map
作为返回类型。
有人可以对此发表评论吗?什么用collection.Map
?
答案 1 :(得分:0)
我很好奇为什么你想要m而不是val - 如果你没有尝试将Map重新分配给它自己,事情似乎工作正常,如repl所示,这更符合斯卡拉哲学在可能的情况下更喜欢不变性:
scala> val m = Map("A" -> 1, "BB" -> 2, "CCC" -> 3)
m: scala.collection.immutable.Map[java.lang.String,Int] = Map((A,1), (BB,2), (CCC,3))
scala> val n = m filterKeys { s => s.length < 3 }
n: scala.collection.immutable.Map[java.lang.String,Int] = Map((A,1), (BB,2))
我发现这个问题有点陈旧,考虑到集合类的主要重构,Scala 2.8中你所看到的行为可能会有所不同。
答案 2 :(得分:0)
使用
m.view.filterKeys(x=>x.length <3).toMap