Scala coding standards: braces on one line

scala coding standards claim that

Technically, the Scala s parser supports GNU-style notation with opening brackets in the line after the declaration. Nevertheless, the parser is not terribly predictable when working with this style due to the way the output with comma is implemented. Many headaches will be saved simply by following the curly brace agreement above.

I looked, and I could not find real examples of this. Can anyone explain the reasoning behind this using exmaple? Does anyone encounter problems using curly braces on a new line?

+7
scala
source share
1 answer

Consider this expression:

someElement { // Some code } 

How is this interpreted? Is this an expression (for example, a value or a function call without arguments) followed by a block statement enclosed in curly braces? Or is it a function call with curly braces containing one argument?

If Scala has no output with semicolon & mdash, i.e. if Scala requires the semicolons to mark the end of the statement in the same way as Java, then the two could be easily distinguished, because the first would require a semicolon at the end of the first line. However, the Scala analyzer must determine where the semicolons should be for understanding the code, and sometimes errors. (Both interpretations, depending on the context, are valid, and it is not always possible for the Scala parser itself to resolve ambiguities.)

For example, let's say that someElement is a function with an argument by name. If you try to call it in the Scala REPL, which intends to put the argument (in braces) on another line, you will find that only the occurrence of someElement causes an error:

 > 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 ^ 

That is, you do not even get to braces. However, if you enter the following, then you are fine:

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

But what if someElement is a value? Now we see this in the REPL:

 scala> val someElement = 5 someElement: Int = 5 scala> someElement res1: Int = 5 scala> { | 5 | } res2: Int = 5 

Now REPL accepts the same code on separate lines as two different expressions.

Let it really become ambiguous. Let's say someElement is a value, but now it refers to a function that takes one argument. Let's look at the possible interpretations:

 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 

That is, it is treated as two separate statements: a value followed by a block statement. But:

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

considered as a call to square with argument 5.

The Scala compiler is a little smarter than REPL, since it can see all the code at once and will try to resolve ambiguities, seeing which of the alternatives makes the most sense, but its interpretation may not always match yours.

So, as you can see, putting an open bracket on the same line - if the two expressions are related: mdash, makes the connection explicit and eliminates the ambiguity. Alternatively, if you want expressions to be parsed unambiguously as separate statements, add a semicolon after the first line.

(IMHO, the output of the semicolon is one of the Scala Achilles heels.)

+5
source share

All Articles