为什么在使用cons运算符构建的列表的末尾需要Nil

时间:2014-04-05 13:41:34

标签: scala

我正在学习Scala(编程Scala,第2版,Odersky)。

使用cons运算符构建列表时,我们必须写:

val l = 1 :: 2 :: 3 :: 4 :: Nil

为什么我们最后需要Nil?为什么编译器不能理解4是最后一个元素,所以只需编写它:

val l = 1 :: 2 :: 3 :: 4

3 个答案:

答案 0 :(得分:8)

::的签名大致是:

case class ::[E](hd: E, tl: List[E]) extends List[E]

// which generates this automatically:

object :: {
    def apply[E](hd: E, tl: List[E]): ::[E]
}

Nil的签名大致是:

object Nil extends List[Nothing]

如您所见,::包含元素和列表。 4不是列表,而Nil是。

答案 1 :(得分:2)

实际上,你可以自己动手:

scala> implicit class Listable[A](val value: A) {
     |   def ::[B >: A](other: B): List[B] = other :: value :: Nil
     | }
defined class Listable

scala> val xs = 1 :: 2 :: 3 :: 4
xs: List[Int] = List(1, 2, 3, 4)

scala> val ys = "A" :: "B" :: "C"
ys: List[String] = List(A, B, C)

scala>

答案 2 :(得分:1)

从概念上讲,Scala中的列表是

  • 无(表示空列表)或
  • 头元素和尾元素,这又是一个列表。

::将创建一个包含头元素和尾元素列表的新列表。这是正确的关联。

所以

1 :: 2 :: 3 :: 4 :: Nil 

将被编译为

1 :: (2 :: (3 :: (4 :: Nil)))

从右边开始,第一个列表由4和Nil构成,从而创建一个新列表[4]。然后添加3作为尾部列表的头[4],制作一个新列表[3,4]。等等...

要回答您的问题,Scala需要一个空列表来构造第一个列表。原因就是在Scala中定义列表的方式。