简体   繁体   English

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

[英]Understanding infix method call and cons operator(::) in Scala

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. 但它试图将List(3)传递给nextnt方法。 When i used paratheses, there was no problem 当我使用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. 它首先执行添加,然后执行cons。 So here is the question: What is the difference between gen nextInt 3 :: Nil and 1 + 2 :: Nil ? 所以这里有一个问题: gen nextInt 3 :: Nil1 + 2 :: Nil什么区别?

There are two things of concern here: precedence and 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. 正如sepp2k所提到的,Stack Overflow上的这个问题解释了优先级,认为引用的规则不够完整,并且从Scala 2.7到Scala 2.8的变化非常小。 Differences concern mostly operators ending in = , though. 然而,差异主要涉及以=结尾的运算符。

As for fixity , almost everything in Scala is read left to right, which is what programmers are used to. 至于固定性 ,Scala中的几乎所有东西都是从左到右读取的,这是程序员习惯的。 In Scala, however, operators ending in : are read right to left. 但是,在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. operator ::优先于nextInt ,因为:优先于所有字母。 Therefore, and remembering its fixity, it becomes: 因此,并记住它的固定性,它变成:

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)成为一个中缀表达式将double 1.0添加到2.此语法自Scala 2.10.0起已弃用,并且可能不会出现在Scala 2.11上。

It's about precedence not execution order. 这是关于优先级而不是执行顺序。 + has higher precedence than :: , so a + b :: c parses as (a + b) :: c . +优先级高于:: ,所以a + b :: c解析为(a + b) :: c However infix method calls with regular names have lower precedence, so a foo bc parses as a foo (bc) . 但是,使用常规名称的中缀方法调用具有较低的优先级,因此a foo bc将解析为a foo (bc)

See this question for a list of operators ordered by their precedence in scala. 有关按scala优先级排序的运算符列表,请参阅此问题

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM