理解 Scala 中的中缀方法调用和缺点运算符(::)

发布于 2024-09-07 22:29:12 字数 1087 浏览 2 评论 0原文

我对 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 :: Nil1 + 2 :: Nil有什么区别?

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.

I think I couldn't really understand how cons operator works, here are some things I tried:

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

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:

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 :: Nil and 1 + 2 :: Nil?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

纵山崖 2024-09-14 22:29:12

这里有两件事值得关注:优先级固定性。正如 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.+(2),因为在撰写本文时,1. 被解释为双精度数,使 1.+(2) 成为中缀表达式,将双精度数 1.0 添加到 2。此语法从 Scala 2.10.0 开始已弃用,并且可能不会出现在 Scala 2.11 上。

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. 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. In Scala, however, operators ending in : are read right to left.

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:

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.

淡淡的优雅 2024-09-14 22:29:12

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

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

It's about precedence not execution order. + has higher precedence than ::, so a + b :: c parses as (a + b) :: c. However infix method calls with regular names have lower precedence, so a foo b c parses as a foo (b c).

See this question for a list of operators ordered by their precedence in scala.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文