我是Scala的新手,我很难理解为什么在向Set.contains
以下是使用REPL(2.9.1.final)的快速示例:
scala> val baz = Map("one" -> 1, "two" -> 2)
baz: scala.collection.immutable.Map[java.lang.String,Int] = Map(one -> 1, two -> 2)
scala> baz.values.toSet.contains("asdf")
res3: Boolean = false
为什么我没有在那里出现类型不匹配?
如果我将baz.values.toSet
分配给其他val
,并在其上调用contains
,我执行进行类型检查:
scala> val bling = baz.values.toSet
bling: scala.collection.immutable.Set[Int] = Set(1, 2)
scala> bling.contains("asdf")
<console>:10: error: type mismatch;
found : java.lang.String("asdf")
required: Int
bling.contains("asdf")
^
愚蠢的错误,语言微妙或编译错误?
答案 0 :(得分:12)
好的,所以Set
在其类型参数中是不变的,它的工作原理与
scala> Set(1, 2, 3) contains "Hi"
<console>:8: error: type mismatch;
found : java.lang.String("Hi")
required: Int
Set(1, 2, 3) contains "Hi"
^
但是,就像你说的那样:
scala> Map('a -> 1, 'b -> 2, 'c -> 3).values.toSet contains "Hi"
res1: Boolean = false
我们可以合理得出的唯一结论是,Set
的类型不是 Set[Int]
。如果我们明确告诉scala我们想要一个Set[Int]
,会发生什么?具有显式类型参数的同一段代码工作得很好(即它不能编译):
scala> Map('a -> 1, 'b -> 2, 'c -> 3).values.toSet[Int] contains "Hi"
<console>:8: error: type mismatch;
found : java.lang.String("Hi")
required: Int
Map('a -> 1, 'b -> 2, 'c -> 3).values.toSet[Int] contains "Hi"
^
问题是传递给toSet
方法的推断类型参数。 Scala显然考虑了contains "Hi"
并推断了Int
和String
的润滑(即Any
)