编辑:根据原始答案重写这个问题
该scala.collection.immutable.Set
班是不是在它的类型参数不变性.为什么是这样?
import scala.collection.immutable._ def foo(s: Set[CharSequence]): Unit = { println(s) } def bar(): Unit = { val s: Set[String] = Set("Hello", "World"); foo(s); //DOES NOT COMPILE, regardless of whether type is declared //explicitly in the val s declaration }
Daniel Spiew.. 53
Set
由于集合作为函数的概念,它的类型参数是不变的.以下签名应略微澄清:
trait Set[A] extends (A=>Boolean) { def apply(e: A): Boolean }
如果Set
是协变的A
,由于函数的逆变,该apply
方法将不能采用类型的参数A
. Set
可能是逆变的A
,但是当你想做这样的事情时,这也会导致问题:
def elements: Iterable[A]
简而言之,最好的解决方案是使事物保持不变,即使对于不可变数据结构也是如此.你会注意到它的immutable.Map
一个类型参数也是不变的.
Set
由于集合作为函数的概念,它的类型参数是不变的.以下签名应略微澄清:
trait Set[A] extends (A=>Boolean) { def apply(e: A): Boolean }
如果Set
是协变的A
,由于函数的逆变,该apply
方法将不能采用类型的参数A
. Set
可能是逆变的A
,但是当你想做这样的事情时,这也会导致问题:
def elements: Iterable[A]
简而言之,最好的解决方案是使事物保持不变,即使对于不可变数据结构也是如此.你会注意到它的immutable.Map
一个类型参数也是不变的.
在http://www.scala-lang.org/node/9764 Martin Odersky写道:
"关于集合的问题,我认为非变量也源于实现.常见集合实现为哈希表,它是密钥类型的非变量数组.我同意这是一个有点烦人的不规则性."
因此,似乎我们为此构建原则性理由的所有努力都是误导的:-)
编辑:对于任何想知道为什么这个答案似乎有点偏离主题的人,这是因为我(提问者)修改了这个问题.
Scala的类型推断足以让你知道在某些情况下你需要CharSequences而不是字符串.特别是,以下内容适用于2.7.3:
import scala.collections.immutable._ def findCharSequences(): Set[CharSequence] = Set("Hello", "World")
至于如何直接创建immutable.HashSet:不要.作为一个实现优化,少于5个元素的immutable.HashSets实际上不是immutable.HashSet的实例.它们是EmptySet,Set1,Set2,Set3或Set4.这些类是immutable.Set的子类,但不是immutable.HashSet.