【发布时间】:2018-03-25 09:00:30
【问题描述】:
在 Scala 中,List 被实现为链表。它有 2 个部分,头部和尾部。 List 中的最后一个单元格包含 Nil。
Scala 中的 Nil 本身就是一个单例并且扩展了 List[Nothing], as documented here
由于 Nil 是单例,是否意味着 Scala 中所有 List 实例的结束元素都具有相同的对象。
【问题讨论】:
在 Scala 中,List 被实现为链表。它有 2 个部分,头部和尾部。 List 中的最后一个单元格包含 Nil。
Scala 中的 Nil 本身就是一个单例并且扩展了 List[Nothing], as documented here
由于 Nil 是单例,是否意味着 Scala 中所有 List 实例的结束元素都具有相同的对象。
【问题讨论】:
虽然实际上结束标记始终是单例 Nil,同一个对象,但最后一个元素是之前的那个。
scala> val a = 1 :: 2 :: Nil
a: List[Int] = List(1, 2)
scala> a.last
res10: Int = 2
您可能会争论这些术语,但在这方面,编码人员通常是实证主义者,而事实就是代码所说的。
【讨论】:
:: 和Nil。最后一个:: 的尾部是Nil;它的头部是最后一个元素。
是的,所有列表都以称为 Nil 的空列表结尾。
您可以通过尝试创建一个末尾没有 Nil 的列表来看到这是正确的。
val a = 1 :: 2 // 失败
val a = 1 :: Nil // 成功
val a = scala.collection.immutable.::(1, Nil) // 成功
最后一个案例调用 :: 的案例类构造函数,它扩展了 List,因此创建了一个 List。
案例类::的代码是……
final case class ::[B](override val head: B, private[scala] var tl: List[B]) extends List[B] {
override def tail : List[B] = tl
override def isEmpty: Boolean = false
}
并且操作::是在List对象中定义的,它调用case类::来为你创建一个列表,当你做1 :: Nil这样的事情时。
如下所示:
def ::[B >: A] (x: B): List[B] =
new scala.collection.immutable.::(x, this)
您还可以看到List 上的map 操作的代码如何遍历List 直到达到Nil。
摘自List 类中的map 函数
while (rest ne Nil) {
val nx = new ::(f(rest.head), Nil)
t.tl = nx
t = nx
rest = rest.tail
}
(ne代表不等)
【讨论】: