If only there was a character we could use for indentation that just indicates the level of indentation and we can configure our editor how wide that should be displayed…
I don’t mind mixing braces and indentation. The most important thing to me is the tooling. The IDE and Scalafmt must work together to do what I want. When I copy-paste or move code with arrow keys then my intention is to move the code. If I move that code outside it’s old scope, I don’t want it to keep artifacts from it.
As an example:
// Original code in example
def foo() =
println("foo")
def bar() =
println("bar") // let's say I want to move this with arrow keys in Intellij
???
// how it works: bad for indentation style
def foo() =
println("foo")
println("bar") // this line attaches to the scope of foo because it kept the indentation
def bar() =
???
// how it could work: moving out of scope
def foo() =
println("foo")
println("bar") // moved this one line up with arrow keys
def bar() =
???
// how it could work: moving into another scope (if that's what you wanted)
def foo() =
println("foo")
println("bar") // moved another line up, now attaches to the scope of foo
def bar() =
???
From my perspective, a very sane approach might be to accept that there are two styles that can/should be enforced by the compiler and automatically rewritten to each other at a project level:
All whitespace
All braces (basically exactly like scala 2’s brace syntax rules)
For context of this comment; I work as a tech lead at a large UK streaming company (it doesn’t take much research to correlate my socials - ITV, specifically), running 200-300 services, depending on how you want to count, in Scala 3; so we are heavily on the application development side of Scala usage. We’ve been on Scala since 2.12 and have generally kept up, and we have somewhere around ~50 scala developers, so I’ve felt the pain of the bikeshedding, and it’s a regular discussion that mostly distracts and splits people more than delights and empowers them; interpersonal conflict is a very real issue that this is currently causing regularly.
My ideal preference would be that there is one canonical style, even if the one I least prefer, to completely shut down bikeshedding of code style - the poison here isn’t the specific syntax, as much as it is the fragmentation of syntax. It throws grit into the machinery of working with people, because as all the debates show, it becomes a bikeshedding war with a lot of usages of words like ‘objective’ which inherently gives away that it’s exceptionally subjective. If you have a team of >10 people, that is a lot of voices to try and accommodate and make feel heard, and inevitably that is bad for working with humans. The middle of the road approach of mixing the syntax seems unfortunate and requires a lot of cognitive overhead to internalise the rules of it.
While I am not typically one to prioritise LLM’s needs over humans, the fragmentation of how scala looks can’t be helping the training data and quality of its output.
First of all, thanks for the initiative. Unluckily, I did not work much with Scala 3 and significant whitespace so far, so I cannot give much feedback on that matter. Last time I used Scala 3 I used a mixed approach (e.g. if then else) and hence I am fine with the proposal. I think the important bit would be that the doc is updated accordingly and that scalafmt default would reflect it.
I propose one addition. The current style guide mentions one should only use spaces. Personally, I would recommend the opposite, only use tabs so that individuals can decide on their own what indent width they like – not only in the IDEs but also e.g. on GitHub (GitHub allows to define a personal preference since a while and I hope more websites will follow).
As mentioned by others, I would also add support for } end if because colleagues mixing the two styles keep telling me that they like the end markers for nested while/if/case etc.
Nitpick: the example with object Foo looks wrong to me, the closing } of the while is off by one space (something which would not have happened using \t )
Thanks for pointing to that bug! Yes, and ironically it is a copy-paste error from our original working document when developing this proposal. Machines don’t always render what we mean
@odersky Please, when you get some minutes off, indent the wrong while loop closing as intended in the original post. Edit: Now fixed.
The example should look like this:
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()
}
FWIW, this proposal from Martin and co seems to be quite close to the convention that that I use for the code that I write.
big +1 to having a standard convention.
+1 to not using “end” markers (I’ve never liked/used them, and I don’t see the benefit of them over braces for larger blocks of code).
+1 to using braces for larger blocks of code
+1 to always having code properly indented
-1 to using tabs for code indentation anywhere.
Rather than a blank line to choose, I probably do it a bit more visually. If it is something that is more than approx 60 lines then I would lean towards braces. If it is less than I would generally elide them.
And generally I prefer the Scala code with fewer braces and brackets. I find it a bit more readable and a bit more clean.
I believe that establishing a single “Common Scala Style” might be an elusive goal. Scala’s flexibility and multiple ways of accomplishing similar tasks make it hard to agree on a universal standard. IMO, the addition of quiet syntax in Scala 3 put the nail in the coffin of this dream.
That being said, I think it would be nice to have a repository of different Scala styles, each with its own set of best practices and guidelines. This could be accompanied by static analysis
tools that help enforce these styles within individual projects or companies. For instance, my company could contribute a document outlining our preferred Scala style and provide a means for
statically analyzing code to ensure it conforms to this standard. This would have its benefits, as it would allow the community to gain insight into which styles are the most widely used or preferred.
Thanks for this. FWIW, I’m in the same camp as people like @halotukozak and @rgwilton, in that I basically already follow the proposed syntax. It’s good, I like it!
End markers are kind of clunky… braces on small code blocks add more hassle / noise than value.. but they come into their own for longer blocks or where more clarity is desirable / needed.
I’d be happy if scalafmt defaulted to something like the proposed style (or if the Scala centre published it as the official scalafmt config, maybe? Perhaps they do, I haven’t looked) and individual people / teams / projects / organisations could tweak and customise from there.
I hear the arguments from the extremes of this debate, from ‘all the braces!’ to none, and I can’t get on-board with either group, personally. I understand, for instance, that some feel Scala’s syntax peaked in Scala 2, but I happen to think the new syntax is a big improvement …as long as it is used sensibly. Getting rid of braces altogether could cause accessibility problems for some users, but equally there are cases where they are often just redundant noise.
All that said, standardising on any style would be good, and I’m sure we’d mostly just grumble and learn to live with whatever the standard was.
People have mentioned “scalafmt defaults”. The current position is that scalafmt rarely changes its defaults, to avoid any element of surprise on users.
However, we can easily add a new preset configuration that specifies the rules that this discussion produces, provided this discussion actually ends, and scalafmt can support these rules.
This is a fine opportunity for Scala Center to run alpine team-building retreats where, instead of solving unusual problems involving ropes and the risk of drowning or falling, software teams work on their shared values of Scala syntax.
Alternatively, it’s an opportunity to produce a reality tv series in which teams are left in various places of geographic isolation, such as an alpine hut in winter or any archipelago, and whoever remains in the last episode gets to pick tabs vs spaces, end markers, how many fewer braces, and so on.
One of the most important parts of the proposal, I think, is the idea that mostly we should be okay with braces and with no braces.
The parallel with parentheses is particularly apt.
Some people might prefer parentheses; some not. That’s okay! You can prefer what you prefer while still having enough expertise looking at the other one to be able to parse it fluently (if less joyfully).
The proposal recognizes that if we make this realization, there are some cases where braces seem to be filling a valuable role for clarity (even if they’re not strictly needed), just like parentheses may (even if they’re not needed). And sometimes they’re clutter (just like parentheses sometimes are). So we should be happy to pursue clarity even if the boundary between the two cases isn’t always perfectly clear, and even if some people like to do other things (e.g. use braces instead of parentheses).
Even more than the proposal for where specifically to decide that braces add clarity, I think the proposal that both are okay deserves serious consideration. Like it or not, because people like each style (and for good reasons, personally), we’re going to have to adapt to being able to read both, if we can. But once we accept that, we have the freedom to write both when it makes the reading easier. And the proposal suggests a simple rule to help decide when it’s easier vs clutter.
This “wait, both is better than the extremes” realization has come up multiple times before. Scala: not functional or purely functional? For most, the answer is: in between is best. No symbolic operators, or symbolic operators everywhere? In between is best. Variable assignments always or fluently chained operations always? In between is best. In each case there are good reasons in some cases to choose one, and good reasons to choose the other, and usually those reasons are more important than the advantage of consistency (consistency is an advantage, but a modest advantage).
Hear, hear. I mean, I’ve been one of the loudest voices for many years of, “Don’t take away my curlies!” But I think there’s a good compromise to be found here, that produces least-bad comprehensibility overall, and it’s worth experimenting with that and seeing where the balances are. So I plan to try adopting this proposal experimentally in my own code, and seeing what my team and I think of the result.
(I was teaching another variant of this principle an hour ago, giving a introductory talk about type classes, including when to use them vs traditional OO interface inheritance. Again, it’s not a simplistic either/or – each has its place, and it’s best to be thoughtful about what’s best under what circumstances.)
I like the proposal, especially the part suggesting that we avoid end markers in favor of braces for longer code blocks.
I believe that introducing (and especially overusing) end markers basically demonstrates the failure of significant indentation itself.
However, I can’t help but quote the message above:
I wrote about this in another thread too. Look, code mancrafting is mostly over, like it or not.
And from that perspective, braces do win — for LLMs they’re easier to comprehend, simpler to write, and they make it easier to keep Scala 2 and Scala 3 codebases aligned.
And Scala doesn’t have the luxury that Python can afford — Scala is far more sophisticated, whereas its codebase is several times smaller than the latter’s.
Overall, I’d go with the proposal, with the caveat that significant indentation should only be used for simple, unambiguous blocks. That can be seen as a small evolutionary improvement over Scala 2 syntax. And when the code becomes more complex, it’s better to fall back to braces.
On the topic, the proposed style is the exact style we use in Scalus (scalus.org), so I obviously support it as it’s clearly superiour to everything else. It’s simple, unambigious, readable, less “prickly”, and LLMs, tools, and people like it.
About the comments that none of this matters anymore because of LLMs. I am completely aware that this is not the most fundamental problem, and certainly not the highest priority issue we work on. But we have to get our house in order, in particular for making things easier for LLM code generation. So this is one small effort to do that.