Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala coding standards: curly braces on the same line

Tags:

scala

The scala coding standards state that

Technically, Scala’s parser does support GNU-style notation with opening braces on the line following the declaration. However, the parser is not terribly predictable when dealing with this style due to the way in which semi-colon inference is implemented. Many headaches will be saved by simply following the curly brace convention demonstrated above.

I've looked, and I couldn't find any real examples of this. Can anyone explain the reasoning behind this with an exmaple? Has anyone run into problems with using curly braces on a new line?

like image 453
Danny Avatar asked Mar 10 '18 10:03

Danny


People also ask

Should curly braces appear on their own line?

We strongly recommend you format your curly brackets following Java conventions: Do not put a new line before an opening curly bracket. Always start a new line after an opening curly bracket. A closing curly bracket should always belong on a separate line, except for else statements.

What are the code between the curly braces?

Blocks: The code between a pair of curly braces within any method or class is called as blocks.

Should curly braces be on their own line C++?

Braces are totally not worth separate line. The thing is that braces are not important.

Where do curly braces go?

This is also welcome in books and blogs that include code samples since more code can fit in less vertical space. The biggest advantage to having the opening curly brace on a separate line is that the curly braces will always line up visually (assuming that we are also using good horizontal spacing in our code).


1 Answers

Consider this expression:

someElement
{
   // Some code
}

How is this interpreted? Is it an expression (such as a value, or a function call with no arguments) followed by a block statement enclosed within braces? Or is it a function call with the braces enclosing a single argument?

If Scala didn't have semicolon inference—that is, if Scala required semicolons to denote the end of a statement in the same manner that Java does—then the two could be easily distinguished because the former would require a semicolon at the end of the first line. However, the Scala parser has to infer where the semicolon(s) need to be to make sense of the code, and sometimes it gets things wrong. (Both interpretations, depending upon context, are valid and it's not always possible for the Scala parser to resolve the ambiguity by itself.)

For example, let's say that someElement is a function with a by name argument. If you attempt to call it in the Scala REPL intending to put the argument (within braces) on another line, you'll find that entering someElement alone 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 don't even get as far as entering the braces. However, if you enter the following, then you're OK:

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 the REPL accepts the same code, on separate lines, as two different expressions.

Let's get really ambiguous. Say someElement is a value, but it's now a reference to a function taking a single 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's treated as two separate statements: a value followed by a block statement. However:

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

is treated as a call to square with an argument of 5.

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

So, as you can see, putting the open brace on the same line—if the two expressions are linked—makes the relationship explicit and removes ambiguity. Alternatively, if you want the expressions to be parsed unambiguously as separate statements, add a semicolon after the first line.

(IMHO, the semicolon inference is one of Scala's Achilles Heels.)

like image 58
Mike Allen Avatar answered Oct 21 '22 01:10

Mike Allen