将元素添加到 Scala 中的不可变列表
Adding elements to an immutable list in Scala
在 Scala 中,将元素添加到不可变列表的方式如下:
val l = 1 :: 2 :: Nil
l: List[Int] = List(1, 2)
这意味着您首先创建一个 Nil(空)列表,然后向其添加 2,然后添加 1。即这些操作是右关联的。因此,实际上,它可以以更清晰的方式重写,如下所示:
val l = (1 :: (2 :: Nil))
l: List[Int] = List(1, 2)
问题来了,如果List要保留插入顺序,空列表先加2再加1,为什么答案不是l: List[Int] = List(2, 1)
??
这只是惯例。列表基本上是堆栈。访问或修改最近添加的项目是最有效的。您也可以按顺序将列表的头部视为最后一项,在这种情况下,您建议的符号将是合适的。
我推测这种约定的原因是我们通常不太关心列表的构造方式,但我们通常希望将访问的第一个项目视为排序中的初始项目,所以符号反映了这一点。
这是因为元素是前置的:首先是 2
然后是 1
。
来自 cons 方法的定义:
def ::[B >: A] (x: B): List[B] =
new scala.collection.immutable.::(x, this)
在这里您可以看到每次创建案例 class scala.collection.immutable.::
的新实例时:
case class ::[B](val head: B, var tail: List[B]) extends List[B]
您只需将新元素用作新列表的 head
,并将之前的整个列表用作其 tail
。
另外,不可变 List
的前置操作需要常数时间 O(1),追加是线性 O(n)(来自 Scala docs)。
在 Scala 中,将元素添加到不可变列表的方式如下:
val l = 1 :: 2 :: Nil
l: List[Int] = List(1, 2)
这意味着您首先创建一个 Nil(空)列表,然后向其添加 2,然后添加 1。即这些操作是右关联的。因此,实际上,它可以以更清晰的方式重写,如下所示:
val l = (1 :: (2 :: Nil))
l: List[Int] = List(1, 2)
问题来了,如果List要保留插入顺序,空列表先加2再加1,为什么答案不是l: List[Int] = List(2, 1)
??
这只是惯例。列表基本上是堆栈。访问或修改最近添加的项目是最有效的。您也可以按顺序将列表的头部视为最后一项,在这种情况下,您建议的符号将是合适的。
我推测这种约定的原因是我们通常不太关心列表的构造方式,但我们通常希望将访问的第一个项目视为排序中的初始项目,所以符号反映了这一点。
这是因为元素是前置的:首先是 2
然后是 1
。
来自 cons 方法的定义:
def ::[B >: A] (x: B): List[B] =
new scala.collection.immutable.::(x, this)
在这里您可以看到每次创建案例 class scala.collection.immutable.::
的新实例时:
case class ::[B](val head: B, var tail: List[B]) extends List[B]
您只需将新元素用作新列表的 head
,并将之前的整个列表用作其 tail
。
另外,不可变 List
的前置操作需要常数时间 O(1),追加是线性 O(n)(来自 Scala docs)。