有人可以解释为什么以下不起作用。当我这样做时,不知怎的会丢失编译类型推断的一些信息toSet
,但我不明白为什么。
scala> case class Foo(id: Int, name: String)
defined class Foo
scala> val ids = List(1,2,3)
ids: List[Int] = List(1, 2, 3)
scala> ids.toSet.map(Foo(_, "bar"))
<console>:11: error: missing parameter type for expanded function ((x$1) => Foo(x$1, "bar"))
ids.toSet.map(Foo(_, "bar"))
^
scala> ids.map(Foo(_, "bar")).toSet
res1: scala.collection.immutable.Set[Foo] = Set(Foo(1,bar), Foo(2,bar), Foo(3,bar))
假设我有以下内容:
trait Pet {
def name: String
}
case class Dog(name: String) extends Pet
val someDogs: List[Dog] = List(Dog("Fido"), Dog("Rover"), Dog("Sam"))
Set
其类型参数不是协变的,但是List
是。这意味着如果我有一个List[Dog]
我也有一个List[Pet]
, but a Set[Dog]
is not a Set[Pet]
。为了方便起见,Scala 允许您在从List
(或其他集合类型)到Set
通过提供显式类型参数toSet
。当你写的时候val a = ids.toSet; a.map(...)
,这个类型参数是推断出来的,你没问题。当你写的时候ids.toSet.map(...)
,另一方面,它不是推断出来的,你就不走运了。
这允许以下操作:
scala> val twoPetSet: Set[Pet] = someDogs.toSet.take(2)
twoPetSet: Set[Pet] = Set(Dog(Fido), Dog(Rover))
虽然这不会:
scala> val allDogSet: Set[Dog] = someDogs.toSet
allDogSet: Set[Dog] = Set(Dog(Fido), Dog(Rover), Dog(Sam))
scala> val twoPetSet: Set[Pet] = allDogSet.take(2)
<console>:14: error: type mismatch;
found : scala.collection.immutable.Set[Dog]
required: Set[Pet]
Note: Dog <: Pet, but trait Set is invariant in type A.
You may wish to investigate a wildcard type such as `_ <: Pet`. (SLS 3.2.10)
val twoPetSet: Set[Pet] = allDogSet.take(2)
^
这值得混淆吗?我不知道。但这是有道理的,这是 Collections API 设计者做出的决定toSet
,所以我们就坚持下去了。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)