理解 Scala 中的中缀方法调用和 cons 运算符 (::)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3181745/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Understanding infix method call and cons operator(::) in Scala
提问by ciuncan
I'm quite new to Scala programming language, and was trying something out stucked in my mind while I was following the lecture notes at here.
我对 Scala 编程语言还很陌生,并且在我按照此处的讲义进行操作时,我正在尝试一些在我脑海中浮现的东西。
I think I couldn't really understand how cons operator works, here are some things I tried:
我想我无法真正理解 cons 运算符的工作原理,以下是我尝试过的一些方法:
I've created a pseudo-random number generator, then tried to create a list of one random value:
我创建了一个伪随机数生成器,然后尝试创建一个包含一个随机值的列表:
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
^
But it tried to pass List(3) to nextnt method. When i used paratheses, there was no problem
但它试图将 List(3) 传递给 nextnt 方法。当我使用 paratheses 时,没有问题
scala> (gen nextInt 3) :: Nil
res69: List[Int] = List(1)
I was curious about the execution order, so i created a function to check it
我对执行顺序很好奇,所以我创建了一个函数来检查它
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)
As seen in outputs, execution order is the same as the order of appearance. Then I thought it might be about the 'nextInt' function, then I tried following:
从输出中可以看出,执行顺序与出现顺序相同。然后我认为这可能与“nextInt”函数有关,然后我尝试了以下操作:
scala> 1 + 2 :: Nil
res72: List[Int] = List(3)
It first executed addition, and after that cons is executed. So here is the question: What is the difference between gen nextInt 3 :: Niland 1 + 2 :: Nil?
它首先执行加法,然后执行 cons。那么问题来了:gen nextInt 3 :: Nil和之间有什么区别1 + 2 :: Nil?
回答by Daniel C. Sobral
There are two things of concern here: precedenceand fixity. As sepp2k mentioned, this question on Stack Overflow explains the precedence, thought the rules, as quoted, are not complete enough, and there were very small changes from Scala 2.7 to Scala 2.8. Differences concern mostly operators ending in =, though.
这里有两件事值得关注:优先级和固定性。正如 sepp2k 提到的,Stack Overflow 上的这个问题解释了优先级,认为引用的规则不够完整,并且从 Scala 2.7 到 Scala 2.8 的变化非常小。但是,差异主要涉及以 结尾的运算符=。
As for fixity, almost everything in Scala is read left to right, which is what programmers are used to. In Scala, however, operators ending in :are read right to left.
至于fixity,Scala 中几乎所有内容都是从左到右阅读的,这是程序员的习惯。然而,在 Scala 中,以 结尾的运算符:是从右到左读取的。
Take, then, this example:
那么,拿这个例子:
1 + 2 :: Nil
First, precedence. What has most precedence, +or :? According to the table, +has precedence over :, so the addition is done first. Therefore, the expression is equal to this:
第一,优先。什么最优先,+或者:?根据表,+优先于:,所以先加法。因此,表达式等于:
((1).+(2)) :: Nil
Now there's no precedence conflict, but since ::ends in :, it has a diferent fixity. It is read right to left, therefore:
现在没有优先级冲突,但由于::以 结束:,它具有不同的固定性。从右到左阅读,因此:
Nil.::((1).+(2))
On the other hand, in this:
另一方面,在这方面:
gen nextInt 3 :: Nil
The operator ::has precedence over nextInt, because :has precedence over all letters. Therefore, and remembering its fixity, it becomes:
运算符的::优先级高于nextInt,因为:它优先于所有字母。因此,记住它的固定性,它变成:
gen nextInt Nil.::(3)
Which then becomes
然后变成
gen.nextInt(Nil.::(3))
At which point the error is obvious.
在这一点上错误是显而易见的。
PS: I'm writing (1).+(2)instead of 1.+(2)because, at the time of this writing, 1.is interpreted as a double number, making 1.+(2)an infix expression adding the double 1.0 to 2. This syntax is deprecated as of Scala 2.10.0, and will probably not be present on Scala 2.11.
PS:我写(1).+(2)而不是1.+(2)因为,在撰写本文时,它1.被解释为双数,制作1.+(2)一个将双 1.0 添加到 2 的中缀表达式。自 Scala 2.10.0 起,此语法已弃用,并且可能不会出现在 Scala 2.11 上。
回答by sepp2k
It's about precedence not execution order. +has higher precedence than ::, so a + b :: cparses as (a + b) :: c. However infix method calls with regular names have lower precedence, so a foo b cparses as a foo (b c).
这是关于优先级而不是执行顺序。+具有比 更高的优先级::,因此a + b :: c解析为(a + b) :: c。但是,具有常规名称的中缀方法调用具有较低的优先级,因此a foo b c解析为a foo (b c).
See this questionfor a list of operators ordered by their precedence in scala.
请参阅此问题以获取按 Scala 中的优先级排序的运算符列表。

