Scala:Nil vs List()

137
在Scala中,NilList()之间有任何区别吗?
如果没有区别,哪一个更符合Scala的惯用风格?无论是创建新的空列表还是在空列表上进行模式匹配。
3个回答

199
scala> println (Nil == List())
true

scala> println (Nil eq List())
true

scala> println (Nil equals List())
true

scala> System.identityHashCode(Nil)
374527572

scala> System.identityHashCode(List())
374527572

在大多数情况下,nil更符合惯用语,并且可以被优先选择。有问题吗?


11
你可以提到 Nil 更符合惯用语。 - Rex Kerr
6
添加了System.identityHashCode以澄清“eq”已经表明它们是同一对象的含义。 - James Iry
20
此外,Nil 直接引用一个对象,而 List() 则是一个方法调用。 - Jean-Philippe Pellet
6
在foldLeft中,List[A]()(而不是Nil)作为累加器值是必要的吗?例如 - scala> Map(1 -> "hello", 2 -> "world").foldLeft(List[String]())( (acc, el) => acc :+ el._2) res1: List[String] = List(hello, world) 在这里使用Nil作为累加器是行不通的。 - Kevin Meredith
6
Map(1 -> "hello", 2 -> "world").foldLeft(Nil: List[String])( _ :+ _._2) - Arneball
显示剩余6条评论

89

User unknown 表明了 NilList() 的运行时值是相同的,但它们的静态类型不同:

scala> val x = List()
x: List[Nothing] = List()

scala> val y = Nil
y: scala.collection.immutable.Nil.type = List()

scala> def cmpTypes[A, B](a: A, b: B)(implicit ev: A =:= B = null) = if (ev eq null) false else true
cmpTypes: [A, B](a: A, b: B)(implicit ev: =:=[A,B])Boolean

scala> cmpTypes(x, y)
res0: Boolean = false

scala> cmpTypes(x, x)
res1: Boolean = true

scala> cmpTypes(y, y)
res2: Boolean = true

在推断类型(例如在折叠操作的累加器中)时,这尤为重要:

scala> List(1, 2, 3).foldLeft(List[Int]())((x, y) => y :: x)
res6: List[Int] = List(3, 2, 1)

scala> List(1, 2, 3).foldLeft(Nil)((x, y) => y :: x)
<console>:10: error: type mismatch;
 found   : List[Int]
 required: scala.collection.immutable.Nil.type
       List(1, 2, 3).foldLeft(Nil)((x, y) => y :: x)
                                               ^

我不明白为什么 2::Nil 可以工作,但 fold 的累加器 y::x 却不行。 - FUD
2
@FUD 好吧,y :: x 确实 可行。问题在于它返回的类型不是预期的类型。它返回了 List[Int],而预期的类型是 List[Nothing]Nil.type(我认为是前者,但也可能是后者)。 - Daniel C. Sobral

29

正如用户unknown的回答所示,它们是同一个对象。

从惯用语上来说,应该优先选择Nil,因为它短小精悍。不过有一个例外:如果由于某种原因需要明确类型,则我认为

List[Foo]() 
比...更好。
Nil : List[Foo]

40
第三个选择是List.empty[Foo] - kassens

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接