21

我对 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
                     ^

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

scala> (gen nextInt 3) :: Nil
res69: List[Int] = List(1)

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

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)

如输出所示,执行顺序与出现顺序相同。然后我认为这可能与“nextInt”函数有关,然后我尝试了以下操作:

scala> 1 + 2 :: Nil
res72: List[Int] = List(3)

它首先执行加法,然后执行 cons。gen nextInt 3 :: Nil那么问题来了:和有什么区别1 + 2 :: Nil

4

2 回答 2

44

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

至于固定性,Scala 中几乎所有内容都是从左到右阅读的,这是程序员的习惯。然而,在 Scala 中,以 结尾的运算符:是从右到左读取的。

那么,以这个例子为例:

1 + 2 :: Nil

首先,优先级。什么最优先,+或者:?根据表,+优先于:,所以先加法。因此,表达式等于:

((1).+(2)) :: Nil

现在没有优先级冲突,但由于::以 结尾:,它具有不同的固定性。它从右到左阅读,因此:

Nil.::((1).+(2))

另一方面,在这个:

gen nextInt 3 :: Nil

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

gen nextInt Nil.::(3)

然后变成

gen.nextInt(Nil.::(3))

在这一点上,错误是显而易见的。

PS:我之所以写,是因为在撰写本文时,它被解释为双精度数,使(1).+(2)中缀表达式将双精度数 1.0 添加到 2。从 Scala 2.10.0 开始不推荐使用这种语法,并且可能不会出现在 Scala 2.11 上。1.+(2)1.1.+(2)

于 2010-07-05T20:58:53.230 回答
3

这是关于优先级而不是执行顺序。+优先级高于::,因此a + b :: c解析为(a + b) :: c。但是,具有常规名称的中缀方法调用的优先级较低,因此a foo b c解析为a foo (b c).

有关按其在 scala 中的优先级排序的运算符列表,请参阅此问题

于 2010-07-05T19:37:01.290 回答