在Scala中,List是以链表的形式实现的。它有两个部分:头部和尾部。列表中的最后一个单元格包含Nil。
在Scala中,Nil本身是一个单例并扩展了List[Nothing],正如这里所记录的。
由于Nil是一个单例,这是否意味着Scala中所有List实例的末尾元素都具有相同的对象?
在Scala中,Nil本身是一个单例并扩展了List[Nothing],正如这里所记录的。
由于Nil是一个单例,这是否意味着Scala中所有List实例的末尾元素都具有相同的对象?
实际上,尽管结束标记总是单例的 Nil 对象,但最后一个元素是紧挨着它前面的那个。
scala> val a = 1 :: 2 :: Nil
a: List[Int] = List(1, 2)
scala> a.last
res10: Int = 2
你可能会对术语提出异议,但编码者在这方面通常是实证主义者,事实是,代码所说的就是真相。
::
和Nil
。最后一个::
有一个尾部是Nil
; 它的头是最后一个元素。 - som-snytt是的,所有的列表都以空列表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对象中,当你执行像1 :: Nil
这样的操作时,它会调用case类::
为你创建一个列表。
如下所示:
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
}