了解Scala中的中缀方法调用和cons运算符(::)

ciu*_*can 19 scala list infix-notation cons operator-keyword

我对Scala编程语言很陌生,在我在这里讲课时,正在尝试一些困扰我的想法.

我想我无法理解cons运算符是如何工作的,这里有一些我尝试过的东西:

我创建了一个伪随机数生成器,然后尝试创建一个随机值的列表:

scala> val gen = new java.util.Random
gen: java.util.Random = java.util.Random@1b27332

scala> gen nextInt 3 :: Nil
<console>:7: error: type mismatch;
 found   : List[Int]
 required: Int
       gen nextInt 3 :: Nil
                     ^
Run Code Online (Sandbox Code Playgroud)

但它试图将List(3)传递给nextnt方法.当我使用paratheses时,没有问题

scala> (gen nextInt 3) :: Nil
res69: List[Int] = List(1)
Run Code Online (Sandbox Code Playgroud)

我对执行顺序感到好奇,所以我创建了一个检查它的函数

scala> def pr(i:Int):Int = { println(i); i }
pr: (i: Int)Int

scala> pr(1) :: pr(2) :: pr(3) :: Nil
1
2
3
res71: List[Int] = List(1, 2, 3)
Run Code Online (Sandbox Code Playgroud)

如输出中所示,执行顺序与外观顺序相同.然后我认为它可能是关于'nextInt'功能,然后我尝试了以下:

scala> 1 + 2 :: Nil
res72: List[Int] = List(3)
Run Code Online (Sandbox Code Playgroud)

它首先执行添加,然后执行cons.所以这就是问题:gen nextInt 3 :: Nil和之间的区别是什么1 + 2 :: Nil

Dan*_*ral 42

这里有两件事需要关注:优先级固定性.正如sepp2k所提到的,Stack Overflow上的这个问题解释了优先级,认为引用的规则不够完整,并且从Scala 2.7到Scala 2.8的变化非常小.=然而,差异主要涉及运营商的结局.

至于固定性,Scala中的几乎所有东西都是从左到右读取的,这是程序员习惯的.但是,在Scala中,结尾的运算符:从右到左阅读.

那么,这个例子:

1 + 2 :: Nil
Run Code Online (Sandbox Code Playgroud)

首先,优先.什么是最优先的,+:?根据该表,+优先于:,所以首先进行添加.因此,表达式等于:

((1).+(2)) :: Nil
Run Code Online (Sandbox Code Playgroud)

现在没有先例冲突,但自从::结束以来:,它有一个不同的固定性.从右到左阅读,因此:

Nil.::((1).+(2))
Run Code Online (Sandbox Code Playgroud)

另一方面,在这:

gen nextInt 3 :: Nil
Run Code Online (Sandbox Code Playgroud)

运算符::优先于nextInt,因为:优先于所有字母.因此,并记住它的固定性,它变成:

gen nextInt Nil.::(3)
Run Code Online (Sandbox Code Playgroud)

然后变成了

gen.nextInt(Nil.::(3))
Run Code Online (Sandbox Code Playgroud)

此时错误很明显.

PS:我写的(1).+(2)不是1.+(2)因为,在撰写本文时,它1.被解释为一个双数,使得1.+(2)一个中缀表达式将双1.0加到2.这个语法从Scala 2.10.0开始就被弃用了,可能不会出现在Scala 2.11上.