什么是点冒号冒号(.::)在scala中的含义

Rah*_*rma 6 scala

下面的代码添加了res列表元素.我的问题是scala内部如何翻译.::符号?

代码段:

var res = List[(Int, Int)]()
res .::= (1, 2)
res .::= (3, 4)
res
Run Code Online (Sandbox Code Playgroud)

输出:

res56:List [(Int,Int)] = List((1,2),(3,4))

And*_*rey 12

该片段中有一些事情正在发生.在深入研究之前,让我们谈谈var和之间的区别val.也就是说,使用val关键字声明的变量是不可变的,即它的值不能更改:

scala> val x = 1
x: Int = 1

scala> x = 2
<console>:13: error: reassignment to val
       x = 2
         ^
Run Code Online (Sandbox Code Playgroud)

另一方面,var关键字用于声明可变变量,即其值可以更改:

scala> var y = "bar"
y: String = bar

scala> y = "foo"
y: String = foo
Run Code Online (Sandbox Code Playgroud)

如果我们想y通过附加到当前值来计算新值,该怎么办?

scala> y = y + "bar"
y: String = foobar
Run Code Online (Sandbox Code Playgroud)

当然有效,但事实证明这是一个简写:

scala> y += "bar"

scala> y
res10: String = foobar
Run Code Online (Sandbox Code Playgroud)

顺便说一下,在Scala中,+只是一个方法的名称,所以y + "bar"是相同的y.+("bar").丑陋,但有效.同样,y.+=("bar")也是有效的替代品y += "bar".

好的,让我们记住以后再说.接下来,正如其他人已经指出的那样,::只是一种将元素添加到列表中的方法(从Java可以调用它someList.$colon$colon(someElement)).需要注意的重要一点是该::方法返回一个新列表:

scala> var letters = List("b", "c")
letters: List[String] = List(b, c)

scala> letters.::("a")
res1: List[String] = List(a, b, c)

scala> letters
res2: List[String] = List(b, c)
Run Code Online (Sandbox Code Playgroud)

如果我们想要设置letters包含字母"a"的列表怎么办?

scala> letters = letters.::("a")
letters: List[String] = List(a, b, c)
Run Code Online (Sandbox Code Playgroud)

请注意,这与前面的字符串示例非常相似.这里的速记也适用吗?

scala> letters ::= "a"

scala> letters
res6: List[String] = List(a, b, c)
Run Code Online (Sandbox Code Playgroud)

是的,它确实.letters.::=("a")也有效.


现在,让我们分解原始片段:

步骤1

创建一个名为的变量,res并为其分配一个空的不可变列表.此空列表旨在包含整数对(Int, Int).

var res = List[(Int, Int)]()
Run Code Online (Sandbox Code Playgroud)

这是另一种做同样事情的方法:

var res = List.empty[(Int, Int)]
Run Code Online (Sandbox Code Playgroud)

(在我看来,这有点容易阅读)


第2步

(1, 2)在列表前添加一个新元素,res并将结果列表重新分配给res.

res .::= (1, 2)
Run Code Online (Sandbox Code Playgroud)

或者,没有空格:

res.::=(1, 2)
Run Code Online (Sandbox Code Playgroud)

看起来很熟悉?我们也可以把它写成:

res = res.::(1, 2)
Run Code Online (Sandbox Code Playgroud)

第3步

前面(3, 4)跟随步骤2中的逻辑


第4步

打印出当前值res,该值应为:List((3,4), (1,2))


边注

令人困惑的是,编译器足够宽松,允许我们在调用时只指定一组括号::,尽管我们确实应该有两个集合:一个用于方法调用,另一个用于指示一对整数.所以,碰巧还有另一种有效的方式来编写同样的东西res.::=((1, 2)).

更普遍:

scala> def first(p:(Int, Int)):Int = p._1
first: (p: (Int, Int))Int

scala> first(6,7)
res0: Int = 6

scala> first((6,7))
res1: Int = 6

scala> first(6 -> 7) //lolz! another one using implicit conversion
res2: Int = 6
Run Code Online (Sandbox Code Playgroud)

隐式转换始终存在,因为它在Predef中定义.ArrowAssoc

心灵=吹

我还建议看一下Scala中语法糖的所有实例是什么?