Towards a Common Scala Style Recommendation

Martin Odersky, Björn Regnell, Rex Kerr

Here is a proposal that was discussed among the signers and some other people. We are opening it up here for wider discussion and feedback.

The question whether to use indentation or braces currently divides the Scala community. One particular problem is that it is perceived as a battle between two different and incompatible styles. But with some modest shifts in details we might be able to overcome that divide and turn it into a matter of degree. This document proposes a path towards a common Scala style that could be used as a recommendation in contexts where an agreed compromise between the braceless and bracefull styles is needed. The goal is to provide a balanced style option that both sides of the divide can appreciate.

A good analogue is comparing with parentheses. Some people write more parentheses than others, but that’s not perceived as a style break. For instance, one person might write:

    x < (n + 1)

But the other person might prefer to drop the redundant parentheses and write:

    x < n + 1

It does not really matter, either way is fine and legible. We should get to a point where one can write:

    def fn(x: Int) =
      val y = x + 1
      y * y

Or one can use braces and write:

    def fn(x: Int) = {
      val y = x + 1
      y * y
    }

Like for parentheses, it does not really matter, either style is legible. There’s universal agreement that even code with braces should be properly indented, so braces are redundant, just like parentheses sometimes are.

There is another problem though, which is that braces often enclose long code blocks and relying on indentation alone sometimes makes it hard to discern the program’s nesting structure. End markers were invented to solve that problem. But once one uses end markers one does adopt a style which is significantly different from braces, so the split into two styles becomes a problem.

The proposal for a common style avoids end markers, and relies on braces to delimit long blocks of code instead. To make this proposal robust, we have to define what a long block is. A definition which we find to work well in practice is to define a long block as a block that contains blank lines: Once one adds blank lines it becomes much harder to discern indentation, so an additional scope delimiter is helpful.

Based on these considerations, here is a an initial proposal of a set of recommendations for a common Scala style:

  1. Prefer braces over end markers.
  2. Use braces around a long scope that is not terminated by some keyword. A long scope is a scope that contains blank lines which are not already embedded in a nested construct. However, braces are not necessary if the scope is already terminated by a closing keyword such as else, do, yield, case, or catch since that keyword effectively serves as the end marker for the scope.
  3. Do consider inserting blank lines following logical structure to make up for the lack of vertical whitespace that was enforced previously by closing braces.
  4. You can also add braces where it aids understanding.
  5. Prefer the new control constructs (e.g. if-then-else, rather than if(...)-else).
  6. For classes and function calls with short bodies: Use : plus indent or braces as you prefer (no recommendation given). Some of the authors of this note do use : in these places and find that it usually improves legibility. But others might disagree.

The systematic application of these rules produces a style that is quiet and clear.

Some people may prefer end markers to braces for long scopes, but we have to be aware that this will cause a split in styles. So the common recommendation avoids end markers.

Tool support: There should be formatting support for these recommendations. In IDEs it would be helpful if we could mark a multiline block, type an opening brace and have the block enclosed in properly aligned braces. For people who are used to end markers, it might also be helpful if an IDE would show them in light grey as comments, similar to how it shows implicit arguments. Something like

    } // end myFunction

Here is a a code snippet that follows these recommendations:

object Foo {

  def bar() =
   while condition do {
     if baz then
       val text = getDataFromSomewhere()
       val arg = argParser.process(text)

       quux(arg)
     else
       bippy()

     doSomethingElse()
   }


  def baz() = someOtherThing()
}

To see how some real-world code looks under these guidelines, here is a link to the Nullables.scala source file of the dotty compiler, #25252 pull request, direct link to file view

Conclusions and way forward

In summary, these recommendations can be described under the catch phrase “use fewer braces”, not “use no braces at all”. We should try them out on more code bases, get feedback from the user community, and once we converged on a set of rules implement them as a style in scalafmt. The goal is to promote the result of this process as an official recommendation.

13 Likes

I think this is a bad idea, and we simply have to accept the divide and move on.

It also makes Scala 3’s decisions weak and cowardly, like walking things back instead of standing by the decision. Brace users would rightfully say: “then why did you make whitespace significant in the first place? You should have never done that. You ruined it for nothing.” Even as a brace-hater, I would have to agree with them.

I think the proposal will make everyone unhappy.

Brace users aren’t avoiding end markers because it’s “too big of a style change.” It’s because they generally don’t want significant whitespace. End markers don’t solve anything for them. For style, they won’t be happy to mix braces and no-braces either, they will find it inconsistent and confusing, having to think about each and every single case and make a decision. They would prefer braces always, not just “long blocks”.

And no-brace users such as myself will not be happy to prefer braces over end markers. I would never, ever use braces over end markers. It’s not a good compromise at all. It’s just a big negative and a big step back from our perspective.

I’m sure there must be some people “in the middle” who don’t feel strongly either way and are happy to mix, but I’d wager it’s a smaller group. And for them, the proposal does not change or provide much (as far as I can tell).

12 Likes

As another no-brace user, this is the first thing that struck me when I read the proposal. I already use end markers when blocks contain blank lines. I can’t see myself replacing them with braces.

3 Likes

To me, a balanced style is what Scala 2 had - no braces around single-line expressions. It was unambiguous, and to this day works perfectly with the style of “write it with any formatting whatsoever, run the formatter, boom it’s beautiful now”.

I think this proposal is a good idea for a default, but I will continue to use and advocate for “scala 2-like” braceful syntax.

7 Likes

To perhaps make things a bit more nuanced: this is a style recommendation aimed at contexts where e.g. a group wants a compromise. A recommendation is not “law”, and the recommendation includes freedom and explicit subjectivity. Every group of devs, company, teacher can leverage the flexible Scala syntax to their benefit as they like, but a common recommendation like this may prove an easy way out to get consistent formatting in a context where that is relevant and also perhaps be a way to reconcile differences.

Are there people here that think a balanced common style recommendation can help in some contexts?

I have seen a wide variety of preferences among students over the last 10+ years that I have taught introductory programming, but on average I see a difference between A) pure beginners to whom Scala becomes their “mother tongue” B) students that come from a language with significant indentation, and C) students that come from a language with braces.

Almost without exception group A and B are very happy with the indentation style and rarely use braces, although some occasionally do use braces also where they still are not a must (e.g. partial functions) and where some occasionally feel like making, what they might think is an uncertain scope limit, more explicit for readability purposes.

The C group is, to simplify, divided in two main sub-groups, the ones that with little effort or frustration just adopts the indentation-based syntax and just move on to that, and the ones that stick with braces and thinks it helps their readability. My hypothesis is that there is a big individual variation how important concrete syntax is to understanding the underlying semantics, and this ability can evolve over time.

I am pragmatic and think, from a teaching perspective, that the flexible Scala syntax should be used to the benefit of individual learning and progress, and that it is perfectly fine to use a style that aids the personal development in embracing new programming ideas, although I encourage everyone to challenge habits and try out the braceless style for a while and see if the happen to like it after some time (and most do, also in group C). But I also think perhaps many companies may want a coding standard and “be done with bike-shedding”…

4 Likes

I am in the camp of i dont care what it looks like, i can read either fine, arbitrary mixing is no problem.

So i do wonder why do people actually think about this stuff? it certainly seems like they do spend a lot of time on it

6 Likes

Seems like a plausible compromise. More concretely, it’s at least somewhat similar to the style I’ve been gradually leaning towards in my own Scala 3 code, so empirically I somewhat agree. The whitespace distinction hadn’t occurred to me as a “breakpoint” for choosing whether to brace or not to brace, but it makes some sense – I’ll play with that.

I’m less sure about preferring if-then-else, but I use them little enough that I’m not sure I care much.

Thanks! I appreciate the thoughtful attempt to move on from the debate.

3 Likes

My only ask (or proposal) would be for “braced end”.

} end C

That is, the line comment, uncommented and verified.

In the middle of a long source text, I shouldn’t need to travel just to know what is ending there.

Perhaps an IDE offers a hover for the close brace.

1 Like

The verification is interesting, and would occasionally be useful, although I’m not sure it’s worth the boilerplate. (And getting the details right feels a bit fraught.)

The IDE hover seems potentially valuable. Many do the highlighting if you set the cursor next to the end brace, but doing it on hover might be slightly easier – worth trying, and seeing whether it results in too much visual friction as you mouse around.

1 Like

About “why” – more of a philosophical question. Many languages have at least one idiom which admits “there’s no accounting for taste”. There’s an entire episode about tabs-vs-spaces in HBO’s Silicon Valley. Most strong “never in my life” arguments come from lack of experience working in heterogeneous environments.

Years ago, members of my team kept arguing during every single code review about where to put line breaks; one camp came from java and was used to a more vertical and verbose style; the other had early scala aficionados who liked the language because it allowed them to use a more compact, horizontal style, and to lean heavily into custom symbolic infix operators.

It also turned out that part of the reason for this bickering was that their eyes were trained to read their style of code, and comprehension during code review was slower as they had to adapt. (A bit like learning to read text in a different alphabet, or one with most vowels omitted; it takes time.) We ended up adopting a mostly horizontal style with a few readability aids, and everyone quickly learned how to read it, and stopped whining.

(This problem, incidentally, led to my involvement with scalafmt, to add two more or less opposing styles in the formatter which completely ignore breaks in the source.)

3 Likes

In my opinion we should not give this “community division” too much attention. It is what it is. As long as we are not forced to use either style i am happy. Some drink their coffee black others with milk. I have nothing against a recommendation, but will not follow it. First i was a (mildly) against the braceless indention style, but now i am a fan. But the end marker is a no-go for me. I use white lines inside methods, classes etc if “logic” (my logic) dictates it, but i see no reason for extra grouping symbols like braces or end markers.

4 Likes

To be clear, the main reason I like this recommendation is for documentation.

The Scala 3 docs and examples have been leaning whole-hog towards braceless, with the result that I find many of the more-complex examples incomprehensible, and I know a lot of people who have been quite turned off by them. That’s counter-productive.

My hope is that this compromise recommendation will make its way into the online examples, and thereby drive home:

  • Yes, it’s a subtle question
  • It’s not a mandatory either/or
  • Here are some examples of how to split the difference

Yes, in the grand scheme of things it doesn’t matter a lot, and never has. But pedagogically it matters, and is relevant to at least some of us who are leading teams with big legacy Scala 2 codebases, who are trying to move in the direction of Scala 3. I care a lot about finding a good evolutionary path that works for experienced teams with ingrained habits, to reduce the friction of migration.

5 Likes

Having a “default”, balanced recommendation is a great idea and might help ease language adoption at large.

I’ll add a few comments, from somewhat different perspectives (I will mark the most salient one with TLDR below):

  • you mentioned tooling, and it’s a valid point
    • while I can’t speak for IDEs, it’s possible that someone, sooner or later, will want to have this logic enforced using scalafmt
    • TLDR: so I’d like to consider this proposal from the formatter point of view, to see how difficult or easy it would be to implement it; I might suggest collecting more feedback and then spending a little time evaluating it from this point of view, before arriving at the final recommendation
    • the first thing that jumped at me is the unenclosed blank lines requirement; perhaps it’s possible but likely unnecessarily complex to implement the “unenclosed” part (the “blank lines” piece is already there)
  • my personal readability angle
    • your def bar example curiously indents the closing brace in do { } not at the while level but at the def bar level; I would assume this was an honest, completely natural human mistake, since def bar (or, rather, while … do {}) is long enough
    • code is not read-only, and here’s the thing about significant indentation: while looking at your code, I wondered which indentation level I would need to use if I had to add an extra statement, either in def baror after it, and decided some sort of marker (end or }) indicating def bar’s indentation level would be extremely useful
    • so, we just need to define what is “long enough”
      • existence of a blank line is a good component; having it “unenclosed” to me is irrelevant as it doesn’t make it visually shorter
      • I can also imagine people writing dense code, without blank lines, so an additional requirement on length would be useful
      • from scalafmt perspective, we tend to prefer cumulative token lengths rather than number of lines since formatting might lead to a different number of lines and thus non-idempotent result
    • quick comment on end markers (still from a personal angle)
      • they remind me of algol/pascal BEGIN/ENDwhich were replaced with… {}(what’s old is new again, I guess)
      • if the goal is having a good mix of style for dorks and dummies, } is shorter and definitely easier to remember than to scratch one’s head for a minute to figure out what magic word to put after end.

I don’t like this proposal myself, not because it is bad, but simply because it doesn’t give enough benefit to be worth it over braces-everywhere that Scala 2 already had for a decade. So might as well stick with braces-everywhere

IMO 90% of the readability problems with indentation stem from using 2 space indents.

  • It looks great in small examples and slides, where a 2 space indent next to a 10-20 character code line looks great
  • It looks bad on real world code, which is typically longer perhaps with 50-100 characters per line, and so 2 space indents are easy to mix up at the margins

The thing is, this is entirely solvable: just use 4 space indents for indentation-delimited code! That’s what Python does, and to me it is the primary reason why indent-delimited Python looks better than indent-delimited Scala

The mixed braces/indents proposal to me is the worst of both worlds: inconsistent, different enough to cause confusion, but not different enough to provide real benefits.

IMO what we should do is:

That was we get two excellent syntaxes that are the best of bith worlds, rather than 1 weird hybrid that is the worst of both worlds

7 Likes

I’d just like to say that it would be great to have a single, recommended Scala style. Even better: format code by default when it’s compiled. The proposal above looks reasonable, +1 from me.

(I already try to use a “default Scala style”: in my projects when possible I use the default scalafmt rules, that is empty settings. It might not always be what I’d choose, but it’s good enough, and cuts any bikeshedding short. Btw. scalafmt is awesome - fast, just works, one of the best pieces of tooling in Scala :slight_smile:)

5 Likes

I like Python. Many, many people do. But… Python allows return statements. Scala inevitably ends up with deeper nesting. Indent of 4 and no end markers work well in Python but not in Scala.

I agree with the original postulate: we can’t go all the way with braceless in Scala, and lots of people might not want to stick with the other extreme.

I am looking at this not as a recommendation for the entire Scala community (as some comments seem to view this). This is a default works-reasonably-well-in-most-cases-without-much-debate recommendation for heterogeneous teams working on a large project in a production environment.

2 Likes

Thank you for detailing your experience, I guess one must factor in that comfort and habits speed up work

I’ll argue the other side of this even though I normally agree with what spamegg1 posts.

I had hoped IDE technology would jump forward to let each of us see equivalent code the way we preferred, but Bemer’s ascii text file idea is just too good.

Perceptions of the split in our community over this issue causes more problems for me using Scala at work than braces or white-space could hope to solve. It’s been a big, uninteresting barrier to upgrading to Scala3, and a false-flag used to abandon Scala altogether.

I welcome this olive branch. Let’s resolve the issue and come back together. We can set scalafmt’s defaults to wherever this conversation lands. Then we can solve more interesting, more valuable problems.

2 Likes

Even my Python ends up wasting too much of my screen space with whitespace on the left, and my Scala is a lot more indented than my Python. Thus, this recommendation implicitly makes very strong assumptions about how indenty your Scala code style is. (For instance: you must use for comprehensions.)

And I still get lost between 7-to-5 and 7-to-4 level deep indenting with longer blocks in Python unless my IDE/editor shows indentation guides. At that point, with very clear guides, almost any depth works.

This is exactly the kind of proposal that argues against 4-space indentation, because it reveals that the pressure to avoid indentation when it helps clarity is real.

Most syntax I’m fine with saying is reasonably a matter of taste. This one, I am happy to declare to be objectively bad. It is much less visually distinct than an indented block. With the block, you don’t even need to be able to read anything to know where it is–you can do it in your peripheral vision. With this, you have to saccade to the last case, and then to whatever is after the last case, and only then do you know where the block ends.

If you tweak your editor to do something else super-striking (like making either case or => inverse, so you can trivially pick it out with peripheral vision), you can get around that. But for any sort of normal syntax highlighting, it is extra busywork for the visual system.

Now, I do agree that the visual salience of two-space indent is less than four-space indent–that also is objectively the case (and judging from people’s comments, there’s considerable variability in how great the perceptual difference is). The thing, though, is that you can rescue the salience of two-space indent with good block indentation guides, which you want to have anyway. You can also rescue visual salience of match blocks with IDE guides, but it’s hard to put them there passively when there’s no space for them because it’s not indented.

Also, for-comprehensions don’t need to have their comprehension part indented! If-statements don’t need to have their conditional indented! But that doesn’t make it a good idea.

val y = 1
val x =
  val a = Option("eel")
  val b =
    if
    y > 0
    then Some(4)
    else None
  for
  xa <- a
  xb <- b
  yield xa * xb
2 Likes

Here are my two cents:
We have to agree on a standard

Official examples will get written, and either they will all use the same style, or they won’t
If they all use the same style, that’s the default style, no matter what we decide officially
If they all use different styles, it will be very hostile to newcomers, and we really don’t want that

So let’s settle on something we can all agree to hate !

I’d even take fully braceful.
(Even though to me it hurts readability)
This has a side benefit: currently, there are a lot of examples that have tabs for Scala 2 and Scala 3, even though the only difference is the braceless style.

There are a lot of standards do not try to be “good”, they are useful because they are a common ground
See for example ISO 3103 - Wikipedia

This is such a standard.

I would be the happiest if the standard we chose is fully braceless, especially if it is in the exact way I write code

But I would be saddest if we didn’t chose anything

3 Likes