@SerialVersionUID(-6084104484083858598L) // value computed by serialver for 2.11.2, annotation added in 2.11.4
sealed abstract class List[+A] extends AbstractSeq[A]
with LinearSeq[A]
with Product
with GenericTraversableTemplate[A, List]
with LinearSeqOptimized[A, List[A]]
with Serializable {
override def companion: GenericCompanion[List] = List
import scala.collection.{Iterable, Traversable, Seq, IndexedSeq}
def isEmpty: Boolean
def head: A
def tail: List[A]
// New methods in List
/**Adds an element at the beginning of this list.
* @param x the element to prepend.
* @return a list which contains `x` as first element and
* which continues with this list.
*
* @usecase def ::(x: A): List[A]
* @inheritdoc
*
* Example:
* {{{1 :: List(2, 3) = List(2, 3).::(1) = List(1, 2, 3)}}}
*/
def ::[B >: A] (x: B): List[B] =
new scala.collection.immutable.::(x, this)
.....
}
下面是scala.collection.immutable.::的定义。
@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
}
var res = List[(Int, Int)]()
res ::= (1, 2)
res ::= (3, 4)
res
内部冒号::实现如下:
/**Adds an element at the beginning of this list.
* @param x the element to prepend.
* @return a list which contains `x` as first element and
* which continues with this list.
*
* @usecase def ::(x: A): List[A]
* @inheritdoc
*
* Example:
* {{{1 :: List(2, 3) = List(2, 3).::(1) = List(1, 2, 3)}}}
*/
def ::[B >: A] (x: B): List[B] =
new scala.collection.immutable.::(x, this)
3条答案
按热度按时间j2cgzkjk1#
这段代码中有几件事正在发生。在深入讨论之前,我们先来谈谈
var
和val
之间的区别。也就是说,使用val
关键字声明的变量是不可变的,即它的值不能被更改:另一方面,
var
关键字用于声明可变变量,即它的值可以被更改:如果我们想要通过将
y
的当前值追加到其当前值来计算其新值,该怎么办?当然,这很管用,但事实证明,这样做有一个简略的方法:
顺便说一句,在Scala中,
+
只是一个方法的名称,所以y + "bar"
与y.+("bar")
相同。很难看,但很有道理。同样,y.+=("bar")
也是y += "bar"
的有效替代品。太好了,让我们以后记住这一点。接下来,正如其他人已经指出的那样,
::
只是一个将元素“前置”到列表中的方法(从Java中,它可以作为someList.$colon$colon(someElement)
调用)。需要注意的重要一点是,::
方法返回一个新列表:如果我们希望将
letters
设置为包含字母“a”的列表,该怎么办?请注意,这看起来与前面的字符串示例非常相似。速记在这里也能用吗?
是的,确实如此。
letters.::=("a")
也可以使用。现在,我们来分析一下原始的代码片段:
第一步
创建一个名为
res
的变量,并为其分配一个空的、不变的列表。此空列表旨在包含整数对(Int, Int)
。这里有一种替代方法来做同样的事情:
(在我看来,它更容易阅读)
第二步
将新元素
(1, 2)
附加到列表res
,并将结果列表重新分配回res
。或者,不带空格:
看起来眼熟吗?我们也可以写成:
第三步
按照步骤2中的逻辑准备
(3, 4)
第四步
打印出
res
的当前值,应为:List((3,4), (1,2))
附注
令人困惑的是,编译器非常宽松,只允许我们在调用
::
时指定一组括号,尽管我们实际上应该有两组括号:一组用于方法调用,另一组用于指示一对整数。因此,碰巧还有另一种有效的方法来编写相同的内容。更笼统地说:
隐式转换一直存在,因为它是在Predef中定义的。ArrowAssoc
头脑=炸开了
我还推荐看看What are all the instances of syntactic sugar in Scala?
bz4sfanl2#
只调用方法
用于对类的示例进行方法调用的
.
(点)。::
是在List
上定义的方法::
是在List
类中声明的方法,它创建scala.collection.immutable.::
类的示例。请注意,
::
是List类中的方法,并且::
是包scala.collection.immutable
中的最后一个类Scala标准库
下面是
List
类中::
函数的实现下面是
scala.collection.immutable.::
的定义。hlswsv353#
的产出
应该是
列表((3,4),(1,2))
因为冒号方法::将一个元素添加到列表的前面。
点
.
在这种情况下是完全可选的-这只是为了明确说明,您正在对列表对象res
调用方法::
。这意味着您的代码等同于下面的代码:内部冒号
::
实现如下:创建一个新列表(因为具有不变性),将参数作为第一个元素,将当前列表内容作为其余元素