Scala 中 :: 和 Nil 类型的区别

Difference between :: and Nil types in Scala

我正在学习 Scala 并使用 List 并创建一个字符串列表,如下所示:

val myList = List("Laptop", "Mouse", "Keyboard", "screen")

从文档中,我得到:

an abstract class List in the scala package, which comes with two subclasses for :: and Nil

根据 class 的定义,我得到:

@SerialVersionUID(509929039250432923L) // value computed by serialver for 2.11.2, annotation added in 2.11.4
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
}

@SerialVersionUID(0 - 8256821097970055419L)
case object Nil extends List[Nothing] {
  override def isEmpty = true
  override def head: Nothing =
    throw new NoSuchElementException("head of empty list")
  override def tail: List[Nothing] =
    throw new UnsupportedOperationException("tail of empty list")
  // Removal of equals method here might lead to an infinite recursion similar to IntMap.equals.
  override def equals(that: Any) = that match {
    case that1: scala.collection.GenSeq[_] => that1.isEmpty
    case _ => false
  }
}

但是文档没有说明什么时候创建了 NIL 对象,什么时候创建了 :: subclass 对象。

两者有什么区别,请指教,什么时候用:: subclass,什么时候用NIL subclass?

当您使用 List(..) 语法时,编译器将使用 List 的伴随对象中定义的 List.apply:

override def apply[A](xs: A*): List[A] = xs.toList

您实际上看不到列表的创建,因为它是根据 Scala Collection Library 的定义方式一般创建的。

::Nil的区别是前者表示有头有尾的链表,后者表示没有元素的空链表。

我们也可以直接使用::Nil定义一个列表:

val list = "Laptop" :: "Mouse" :: "Keyboard" :: Nil

翻译成:

val list = Nil.::("Keyboard").::("Mouse").::("Laptop")

其中 :: 不是指类型 ::,而是指 List[A] 上的方法:

def ::[B >: A] (x: B): List[B] = new scala.collection.immutable.::(x, this)