编辑:根据原始答案重写这个问题
该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
}
Run Code Online (Sandbox Code Playgroud) 在Scala中,a Set是一个函数:
trait Set[A] extends (A => Boolean)
Run Code Online (Sandbox Code Playgroud)
这使得不可能具有协变不可变Set因为类型A发生在逆变位置.相反Seq,未定义为函数.关于为什么以这种方式设计集合和序列的问题已经有一些内容:
一个答案说,其原因是数学背景.但这个答案没有多解释.那么,定义一个Set函数的具体优势是什么?如果以不同的方式实现它会有什么缺点?
与此Scala类似:为什么Seq.contains包含Any参数,而不是序列类型的参数?
如果你这样做
Seq(1, 2, 3).contains("dasdas")
这将编译并始终返回false。是否有引发类型错误的替代方法?这似乎是一个主要的wtf,contains总是返回false并且非常容易在代码审查中遗漏。
看来选项.contains()并不总是按预期工作。我有以下代码:
case class Person (name: String, nickName: Option[String])
val people = Seq(Person("Ned", Some("d")), Person("Alex", None))
val suspects = Map("c" -> 1, "d" -> 2)
val result1 = people.filter(_.nickName.contains(suspects.contains(_)))
val result2 = people.filter{ p =>
p.nickName.contains{ n =>
suspects.contains(n)
}
}
println(result1)
println(result2)
Run Code Online (Sandbox Code Playgroud)
你可能期望result1并result2包含一个人,但他们实际上是空的。为什么?
事实证明以下代码有效:
val result3 = people.filter{ _.nickName match {
case Some(n) => suspects.contains(n)
case None => false
}
}
val result4 = people.filter( _.nickName.map(suspects.contains).getOrElse(false))
val result5 = people.filter( _.nickName.fold(false)(suspects.contains))
println(result3)
println(result4)
println(result5) …Run Code Online (Sandbox Code Playgroud)