Feedback sought: Optional Braces

Overall I think it’s a reasonable syntax. Historically, we can look at F# and Haskell to see that when given a choice, with both brace-delimited and indent-delimited syntaxes are available, people generally end up picking the indent-delimited version. Python’s success also speaks for itself; beginners certainly don’t pick Python because of performance, ease of installation, packaging, IDE support, or simplicity of the language’s runtime semantics!

I’m generally in favor of this indent-delimited Scala, as long as:

  1. The exact syntax has time to be bikeshedded over and argued about, so we don’t get stuck long term with a sub-optimal or warty design simply for lack of discussion

  2. We find a solution to avoiding braces when calling higher-order functions with multi-line lambdas. Higher-order functions are common enough that we cannot claim to have brace-free Scala unless they’re supported, and it’s generally accepted that indent-delimited blocks and multi-line lambdas are a challenging pair of requirements to satisfy https://stackoverflow.com/questions/1233448/no-multiline-lambda-in-python-why-not

  3. We have a best-effort backwards-compatibility plan and migration plan. As Scala 3 is a big release, I expect upgrading to be painful, but hopefully indent-delimited blocks do not make it more so

I’ve a ton of experience using indent-delimited syntax: I’ve used Python regularly for my entire career, I spent years working in Coffeescript, and have done some work in F#. But as much as I like indentation-syntax, there is definitely ways you can do indent-delimited syntax badly:

  1. Coffeescript ends up making too many delimiters optional (parens and commas, in addition to braces and curlies) resulting in code that is challenging to skim.

  2. Coffeescript also commonly used two space indents, which visually make distinguishing blocks much harder than code using four space indents, more so because of the lack of explicit delimiters

  3. F# has a pretty unusual/irregular syntax overall, so despite being indent-delimited I find it much less pleasant to read than curly-heavy C# or Scala

Thus it’s not sufficient to do indentation syntax in Scala, but we also have to do it right.

Looking at the linked ExtractSemanticDB.scala file, I have the following concrete feedback:

  1. I still find the two-space indentation makes it very hard to distinguish blocks when skimming. Normally I don’t discuss formatting concerns, but given that this whole effort is about improving Scala’s surface syntax, I think this is important. After spending years reading 2-space-indented Coffeescript, I don’t think this response to 2-space indents is going to change for me

  2. The code snippet has a distinct lack of multi-line lambdas being passed to higher-order functions. I understand that those would be the “worst case” scenario for the whitespace rules as currently specced and implemented

  3. The (inconsistently applied?) indentation of case blocks within a match statement seems extraneous. With curlies it looks a bit more reasonable, but without curlies it seems a lot more awkward to have two levels of indentation where an if/else if/else chain would only have one

Given that we’ll be stuck with this syntax for the long haul we need to make sure it’s the best syntax we can come up with. While the current set of rules that are specced out is very reasonable, I do think that arguing out these last few concerns (and any other concrete concerns that people bring up) is definitely worth doing before the spec and implementation are set in stone for the next decade.

19 Likes