我对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 :: Nil
和1 + 2 :: Nil
之间的区别是什么?
答案 0 :(得分:41)
此处有两件事需要关注:precedence和fixity。正如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中的优先级排序的运算符列表。