在Scala中使用集合时,通常需要将集合的空实例用于基本案例。因为默认的空实例使用类型参数Nothing
扩展集合类型类,所以它有时会使类型推断无法直接使用它们。例如:
scala> List(1, 2, 3).foldLeft(Nil)((x, y) => x :+ y.toString())
<console>:8: error: type mismatch;
found : List[String]
required: scala.collection.immutable.Nil.type
List(1, 2, 3).foldLeft(Nil)((x, y) => x :+ y.toString())
^
失败,但以下两项更正成功:
scala> List(1, 2, 3).foldLeft(Nil: List[String])((x, y) => x :+ y.toString())
res9: List[String] = List(1, 2, 3)
scala> List(1, 2, 3).foldLeft(List.empty[String])((x, y) => x :+ y.toString())
res10: List[String] = List(1, 2, 3)
我遇到类似困境的另一个地方是定义默认参数。这些是我能想到的唯一例子,但我知道我见过其他人。提供正确类型提示的一种方法通常优于另一种方法吗?是否存在各自有利的地方?
答案 0 :(得分:1)
我倾向于使用Nil
(或None
)结合告诉类型参数化方法类型(如Kigyo)给出的特定用例。虽然我认为使用显式类型注释对于给定的用例同样可行。但我认为有些用例需要坚持使用.empty
,例如,如果你试图在Nil: List[String]
上调用一个方法,首先必须将其包装在大括号中,这样就可以了 2个额外的角色!! 。
现在使用.empty
的另一个参数是与整个集合层次结构的一致性。例如,您无法执行Nil: Set[String]
而无法执行Nil: Option[String]
,但您可以执行Set.empty[String]
和Option.empty[String]
。因此,除非您确定您的代码永远不会被重构到其他集合中,否则您应该使用.empty
,因为它需要更少的faff来重构。此外,保持一致是一般的好吗? :)
公平地说我经常使用Nil
和None
因为我经常确定我永远不想使用Set
或其他东西,事实上我会说最好使用Nil
当你真正确定你只会处理列表时,因为它告诉读者代码“我真的真的在这里处理列表”。
最后,你可以用.empty
和鸭子打字做一些很酷的东西,看一下这个简单的例子:
def printEmptyThing[K[_], T <: {def empty[A] : K[A]}](c: T): Unit =
println("thing = " + c.empty[String])
printEmptyThing[List, List.type](List)
printEmptyThing[Option, Option.type](Option)
printEmptyThing[Set, Set.type](Set)
将打印:
> thing = List()
> thing = None
> thing = Set()