Scala编码标准:同一行上的花括号

时间:2018-03-10 10:20:53

标签: scala

scala coding standards状态

  

从技术上讲,Scala的解析器确实支持GNU样式表示法,并在声明后的行上打开括号。但是,由于实现了分号推断的方式,解析器在处理此样式时并不是非常可预测的。只需遵循上面演示的大括号惯例,就可以节省许多麻烦。

我看了,我无法找到任何真实的例子。任何人都可以用exmaple来解释这背后的原因吗?有没有人在新线上使用花括号时遇到问题?

1 个答案:

答案 0 :(得分:5)

考虑这个表达式:

someElement
{
   // Some code
}

这是如何解释的?它是一个表达式(例如一个值,或一个没有参数的函数调用)后跟一个括在括号内的块语句?或者它是一个函数调用,括号括起一个参数?

如果 Scala 没有分号推断 - 也就是说,如果 Scala 需要使用分号来表示语句的结尾,其方式与 Java <相同/ em>然后这两个可以很容易区分,因为前者在第一行的末尾需要一个分号。但是, Scala 解析器必须推断分号需要用于理解代码,有时它会出错。 (根据上下文,这两种解释都是有效的,并且 Scala 解析器并不总是能够自行解决歧义。)

例如,假设someElement是一个带有名称参数的函数。如果您试图在 Scala REPL 中调用它,打算将参数(在大括号内)放在另一行上,您会发现单独输入someElement会导致错误:

> scala
Welcome to Scala 2.12.4 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_161).
Type in expressions for evaluation. Or try :help.

scala> def someElement(x: => Int): Int = {
     |   // Do something...
     |   x
     | }
someElement: (x: => Int)Int

scala> someElement
<console>:13: error: missing argument list for method someElement
Unapplied methods are only converted to functions when a function type is expected.
You can make this conversion explicit by writing `someElement _` or `someElement(_)` instead of `someElement`.
       someElement
       ^

也就是说,你甚至没有进入大括号。但是,如果您输入以下内容,那么您就可以了:

scala> someElement {
     |   10
     | }
res0: Int = 10

但如果someElement是一个值呢?现在我们在 REPL

中看到了这一点
scala> val someElement = 5
someElement: Int = 5

scala> someElement
res1: Int = 5

scala> {
     |   5
     | }
res2: Int = 5

现在 REPL 在不同的行上接受相同的代码,作为两个不同的表达式。

让我们变得非常暧昧。假设someElement是一个值,但它现在是对一个参数的引用。让我们来看看可能的解释:

scala> def square(a: Int) = a * a
square: (a: Int)Int

scala> val someElement = square _
someElement: Int => Int = $$Lambda$1034/1609754699@74abbb

scala> someElement
res3: Int => Int = $$Lambda$1034/1609754699@74abbb

scala> {
     |   5
     | }
res4: Int = 5

也就是说,它被视为两个单独的语句:一个值后跟一个块语句。但是:

scala> someElement {
     |   5
     | }
res5: Int = 25

被视为对square的调用,参数为5。

Scala 编译器比 REPL 稍微聪明一点,因为它可以同时看到所有代码,并会尝试通过查看哪些替代方案来解决歧义最有意义,但它的解释可能并不总是与你的相符。

因此,正如您所看到的,将开括号放在同一行 - 如果两个表达式是链接的 - 使关系显式化并消除歧义。或者,如果您希望将要明确解析的表达式作为单独的语句,请在第一行之后添加分号。

(恕我直言,分号推断是 Scala Achilles Heels 之一。)