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

时间:2010-07-05 19:26:52

标签: list scala operator-keyword infix-notation cons

我对Scala编程语言很陌生,当我在here跟踪讲义时,我正在尝试一些问题。

我想我无法理解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 :: Nil1 + 2 :: Nil之间的区别是什么?

2 个答案:

答案 0 :(得分:41)

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

对于 fixity ,几乎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.+(2),因为在撰写本文时,1.被解释为双数,使1.+(2)成为中缀表达式将double 1.0添加到2.此语法自Scala 2.10.0起不推荐使用,并且可能不会出现在Scala 2.11上。

答案 1 :(得分:3)

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

请参阅this question以获取按其在scala中的优先级排序的运算符列表。