On braces and indentation-based syntax

Monolinguists tell us the only option to their handicap is a tyranny of the majority gulag.

I happen to know you. And I know you are plenty smart enough to read both styles.

I argue it’s actually good for avoiding ossification of the brain to exercise in both styles.

I find exactly the opposite. Things used once and given superfluous names so they can be used slightly later are hard to understand.

And anyway, someone suggested that if you don’t like it, just don’t use it. Scala supports your preferred approach, too. Why not stick with that?

2 Likes

When there is an irresolvable bifurcation of preferences, then the decision has to be made whether to favor one over the other, or to accommodate both.

The braceless indentation versus braced style of coding is an irresolvable difference. They are two distinct styles. If you want to appeal to those who emphatically prefer braceless, then you can attract that crowd by offering it. If you don’t care about them, then they can go write a transpiler which what I was going to do otherwise. But I would really prefer the syntax highlighting in the IDE. So either way there will be a bifurcation. By snubbing the other side there is only animosity created without accomplishing your gulag goal. You can’t lock people in a jail if they feel strongly enough about their preferences. Coase’s externalities apply.

As for very long lambdas I don’t mind if it is in the language, but what I am advocating is not to make a bunch of complex special cases. Find one regular syntax that enables it coherently such as the colon proposal, which has other benefits as I pointed out.

Then yes I can avoid the long lambdas as I wish and you can have them as you wish. Another benefit of naming long lambdas is reuse as you mentioned in those cases where the function is passed more than once.

ADD: obviously there is already curly braces for very long lambdas. So either braceless support for long lambdas could be forsaken as not worth the confusion, or perhaps there can be some regular syntax that has wider applicability (not just a special case) which is also less implicit (thus less perplexing to the newbie) such as the proposed colon syntax for starting a block on the same line. Since when did blocks become lambda parameters in Scala? I guess I missed that the first time I learned Scala. I hope that is conspicuous in the Scala Book.

How do you line up long blocks without indenting braced code?

I genuinely can’t fathom how indented blocks could be harder to read than non-indented code with braces? Please enlighten me.

Is it that the IDE highlights the matching braces? So nesting is visualized more readily? Note the IDE could be programmed to highlight the equivalent matching ends with braceless as well.

Where did you see me saying not to indent? I have never advocated that. I’m saying that the lack of braces makes the code unreadable to me, beyond a modest level of complexity. That has nothing to do with indentation.

2 Likes

Okay I found the specification I had seen in the past days when I was reviewing Scala 3:

https://dotty.epfl.ch/docs/reference/other-new-features/indentation.html

So my memory was correct that the colon is optional in some cases and there are some complex rules about what line endings can trigger an eligible indentation block. This sort of complexity is what I am railing against.

Much simpler would be that indentations always begin at 3 spaces and if the parser detects a block where there shouldn’t be one, then error. Then we do not need all these special cases in the aforelinked specification. Also as an additional benefit line continuations will be enabled, just don’t indent them to a multiple of 3 spaces. Please simplify. The current design is repeating the same mistake made in the past that makes Scala so unnecessarily abstruse. Pick the simpler rule please. It is known as the Keep It Simple Stupid principle (mods please do not blame me as I did not coin the term and it actually doesn’t have derogatory meaning).

@martijnhoekstra, I share your cognitive dissonance that seems to stem from how unintuitive it is for a function to take a block as an input parameter. This is quite strange. And putting long lambdas in curly brace blocks to make them input parameters is also strange. Granted a necessary power user feature, yet still strange. Any newbie is going to stumble on that.

Yet your example is even more weird because it isn’t a lambda. I suppose it is passing a Unit type? It seems to me that Unit types should always be passed as some delimited block, yet for you the colon does not connote a block, because it has a different usage in other programming language contexts you are familiar with. Where in Scala has the colon been used to delimit a name and its definition? I am not familiar with that usage. Or maybe you are referring to a different language?

So the attempt to make it more natural by putting the parameter list of the lambda and arrow on the same line as the function makes the block body that follows somewhat more intuitive but it is a special case that has inconsistencies such as the single line case requires parentheses because the parser can’t easily distinguish it and the multiple parameter list function (which Odersky argues is non-idiomatic code, at least with the arrival of Scala 3, although others disagreed) seems to have no indented style that isn’t fugly and non-intuitive. And the non-lambda Unit block as a function parameter are a different case.

My thought is that Unit parameters are power user material. Maybe they should remain curly braces? To make it very explicit that they are blocks. Passing Unit to a function is very weird to someone who is new to Scala. Maybe we should explicitly call that out to the newbies who are adopting the braceless style.

If you adopt my suggestion for hardcoding the indent for braceless blocks then you do not need the prefixed colon for lambdas, as either you will have a line continuation or an indented block defined by the next line’s indentation. Single-line lambdas (and I suppose maybe also line continuations?) require parentheses presumably as they always did?

Multiple parameter lists (and I guess actually any comma-delimited parameter list) taking a block lambda or Unit block as any but the last parameter should be required to take curly braces which would accomplish both Odersky’s objective to discourage them (the multiple parameter lists) as much as possible and address the complaints of others about how unreadable they are otherwise in convoluted braceless styles?

EDIT: comma (or colon) delimited braceless blocks are also fugly, hard-to-read and shouldn’t be allowed? Tl;dr Unit parameter blocks are always curly braced. Lambda (and counterparts) braceless blocks allowed but only as the last parameter, otherwise must be curly braced.

EDIT#2: Regarding my suggestion to adopt 3 spaces as the standard and enforced indent, it would resolve the potential bug pointed out in that long January discussion thread which is closed so I can’t reply there:

class A
 object B

There was a big thread about this a while back, here’s an example from there that shows one example of the sort of code that can be difficult to visually parse for some developers:

Basically, without braces acting as punctuation, it’s very easy to lose track of what level of indentation something is at, particularly when there’s stuff between it and the reference line that opens the block. At least for me, it’s a visual processing thing, and doesn’t appear to be something that I can brute-force my way through (kind of like if a programming language mandated that the background be red and identifiers green).

Note if ensureC is stretches above the top of your window, the closing brace is not going to be unambiguous. The vertical lines could be colored so you do not have to count them. The IDE could be easily programmed to take you directly to (or pop it up) the previous line of the block.

I’m empathetic to your claim to be autistic and dyslexic. I also tested with a spike to maximum in talent on the autistic spectrum and a spike to maximum perception on the neurotypical spectrum. I can’t block out noises well.

Can we find a win-win here? Expand Scala’s ecosystem without harming anyone?

Can’t someone write a translator from block indenting to curly braces so that each style can be translated to the other for reading?

While true, it’s considerably less ambiguous, and the tooling (as it currently exists) needs something to trigger the hint about when the block starts, so it’s much easier to handle.

The other issue is that, for me, the sample is difficult to read even when the entire sample code is entirely contained in a single screen, so it’s a situation of “can be bad some of the time” vs “always bad, sometimes worse.”

This goes back to the frequent complaint that this was done way too fast, and dismissing concerns by referencing tooling that doesn’t currently exist has been both annoyingly common and not particularly helpful or reassuring.

While I am autistic, I’m not dyslexic - it’s just the closest analog that seems to make sense to people when I describe how I see these code blocks.

We might have been able to, if this had been handled differently. As is, this is going to really screw over Scala because it’s going to relegate Scala to small companies only. As soon as you move past a handful of developers, the chance you’re going to end up having to pass on a really attractive candidate for Sr Engineer because they intensely dislike (or just straight up can’t read) the kind of code the existing team is using grows incredibly quickly.

And that’s not even the worst case: when merging two companies who use Scala, the odds start to look pretty bad that one of the teams is going to bail because they lose the debate over which style to use, and all that institutional knowledge is lost.

Companies tend to be shy about taking on that kind of risk. I’m currently trying to keep our company from moving to Java because of this sort of thing, and I’m honestly not having a lot of success.

This exists for Python. Basically nobody uses it, so it’s probably not great to use. I’d imagine that it’d be worse for Scala, as the lack of braces or their inclusion where they could otherwise be omitted in Scala 2 has been used to signal the presence of side effects or communicate that something is a single expression.

If we’re going to be assuming the existence of hypothetical tooling, IntelliJ is fairly good about guessing when you want to add them (though it’s still hilariously wrong at times), and it’s a lot harder to hide something than add it back if it’s been removed - so if someone really can’t stand braces, they’ve always had options :wink:

FUD and your Parade of Horribles seems to have no effect on me whatsoever. Never took a single clot shot and begged everyone I knew with the killer exosome to please breath in my face and let me taste a sample of their sputum. Kept trying to get a positive test but the darn things don’t seem to correlate with reality—or at least the reality they purport to tell us.

Two religiously opposed companies would never be candidates for a merger regardless if that had chosen two coding styles of Scala, or Python (or my transpiler to braceless Scala) and braced Scala. You will not be able to prevent someone from creating a braceless Scala. Religiously opposed companies will not conform to any jail you intended to impose on them. Arguing for control you don’t possess is a fallacy. It is destiny and if you do not do it officially then you might end up with several different flavors of it which will be a worse outcome (the same point I made about unsigned types, better to embrace it officially and protected by a optional compiler flag because it has a performance penalty, than to not embrace it and end up with 31 flavors of unofficial libraries which is a much more discombobulated outcome). Bite the bullet because ultimately you have no choice and better to take the lead on it officially.

As for a Sr. Engineer he will choose the company that employs the coding style he prefers. I do not see any problem. Unless you are arguing he will need to read the Scala libraries and thus be turned off if they are not in his preferred style. But how many programmers have been turned off from Scala up to now because of the lack of a braceless style? Your argument may have not have any net effect either way. You lose some, you gain some. But for sure the ecosystem will grow because there are two coding styles available to make more people happy.

Personally I would have no objection if the Scala libraries would remain in curly brace style. For me the braceless style is more for the junior users who probably won’t be reading the libraries anyway. Although I am not junior and I will use braceless but I have no problem reading braced. I prefer the cleaner, more uniform braceless (might be my German ancestry, although I also have Welsh, Irish and Swiss-French-Italian)

They must not need Scala features much. Maybe this is a good filter for users who really need Scala and thus will be its most ardent supporters. I absolutely need type classes and anonymous unions, so Java is not an option for me regardless.

Also I think large companies don’t use Scala anyway, because they ostensibly prioritize breadth of the developer pool over esoteric, geek-cool features. Thus they would choose Java or Kotlin regardless. So the threat is probably mostly irrelevant. The braceless option may increase the number of junior Scala developers.

Maybe nobody uses it because Python can’t optionally compile curly brace code so all the curly brace aficionados departed?

I don’t understand why a tool can’t insert a brace deterministically where every braceless block is? If Odersky adopts my suggestion for the simple rule that every block begins on a 3 space indent, there is no ambiguity whatsoever about which are blocks. As for other optional cases which are not required to be blocks and were not explicitly marked as blocks in braceless code, I guess that is what the author intended, so maybe the translated result is correct as the author intended it? Curly braces can be mixed with braceless code.

No because previously the compiler would not compile my braceless code and the IDE did not understand it.

All spaghetti code is hard to read regardless. We should endeavor to write clear code without ridiculous levels of nesting. That is functions are for.

Braces don’t rescue me from bad coders.

This is unfortunate, as my concern is neither of these. Bifurcating the developer pool has never ended well, even for languages with a much larger mindshare than Scala currently enjoys. It was a decade of annoyance that Python is just barely managing to leave behind, and it was a significant factor in the implosion of the Perl community.

That’s … cute. C level execs don’t really care about the technical details of a company they’re looking to acquire, they care about retention, risk, and the cost of hiring. A company built on a Java stack won’t hesitate to acquire a company that’s running a Python stack (or vice versa) because either language is relatively easy to hire for and they expect the mindshare loss to be a Ship of Theseus situation.

They are going to be a bit less interested in picking up company that is built on a tech stack that relies on less familiar languages, and Scala currently still qualifies - but being a JVM language is helpful here because the CTO’s can reassure them that everything will still play nicely together.

They’re going to get really skittish if Scala develops a reputation as “the language with developers that tend to leave en-masse when acquired” - my intuition is that you’ll lose people a lot faster when a single commit can entirely rewrite the code in the disfavored style, rather than the slow process of porting existing software to an entirely new language, however this is untested intuition at the moment.

The problem is they’re already annoyingly difficult to hire for, so reducing the pool of interested candidates further is a Really Bad Idea.

It’s all nice-to-have stuff. There isn’t an algorithm in existence that can be implemented in Scala but not Java. It can be a lot easier, faster, and more pleasant to program in Scala, but let’s not delude ourselves here - if companies can’t reliably hire Scala devs that work well with the existing teams, they’re not going to use Scala. Splitting the developer pool is going to exacerbate this issue.

The issue here is that, once removed, the information about what braces were explicitly included is lost, so the round-trip code can end up looking very different.

You misunderstand, the braces would still be there, the hypothetical tooling you could write would just hide them in the IDE.

1 Like

I had already thought of that, but I guess I should have preempted your misunderstanding as follows.

But you argued there would be no true translation from braceless to braced, thus I would not be able to write my code in braceless to begin with, if we accept your assertion.

And if your assertion is false, then there is no need for any of this acrimony because we can translate back and forth between the styles.

As ever, life is more nuanced. Information can be hidden more easily than it can be reconstructed once lost. It’s simpler to write a filter to hide the braces the IDE would have inserted for you, than it is to reconstruct the braces that a human would have intentionally included or omitted.

The automatic translation is really only a one-way trip, unless you’re willing to accept a lossy translation.

Addendum

And important point you seem to missing is that, normally, a change that makes development marginally easier for some and near impossible for others would have been rejected. In this case, Martin reversed that, and fewerBraces is just another step in that direction.

Yes, you may prefer not to have to deal with braces, but treating that preference as an equal concern to the physical inability to read code without them is all sorts of messed up.

I don’t hate braceless style, braceless style disqualifies me from participation in Scala development.

1 Like

Last I checked the Scala developer pool was so minuscule (on the verge of extinction) it needs any boost it can get. I believe the braceless syntax might provide that boost. It will also further differentiate it from Kotlin which has been eroding Scala’s market share. We need Scala to survive. It has come very close to dying from my perspective. Thus Scala needs a larger ecosystem, so arguing to hang on to the current measily ecosystem instead of trying to expand the ecosystem doesn’t make sense to me. Besides those who absolutely need Scala’s unique features are not so fragile as to abandon it because of the new optional syntax. What they going to migrate to, Haskell? Haskell also has a non-braced syntax.

I am not well versed in Python’s history but wouldn’t the lack of static typing play a significant factor there, because there’s facets of the styling you can’t really get unambiguously right without it. How can one cite Python of an example of what not to do when it has 30% market share compared to Scala’s 0.63% and Kotlin’s 1.44%?

Scala is not going to be the better Java. Kotlin has that locked up. Scala needs another niche.

Do you want Scala to die just because of your intransigence about braces? Will you be happy then? I want Scala to thrive.

Everything here screams for creating a version of Scala that has a larger developer pool. What is your proposal? Scala 2 status quo?

The popularity of Python seems to be a good target. If you can mostly make Scala code resemble the advantages of Python but then add type classes and static typing, you’ve carved out a niche that nobody else has, especially not on the JVM.

Your argument distills down to let’s keep our horrible situation intact and take no steps to attempt to rectify it. You want to preserve what appears to be nearly entirely non-existent. Scala already is a no-go for corporations. We know that. And the only way to change that is to broaden the developer pool.

I bet there won’t be any splitting because the supply of junior devs will expand and overwhelm the small pool of laggard diehards who refuse to adopt the sanctioned braceless default. Those junior devs will eventually become senior devs. We need to recruit junior devs at a faster rate. The braceless style and building libraries to be more friendly to Python developers might be a strategy for achieving that goal. Stuck in the mud with the status quo is not a plan.

Afaik, it’s not possible to adequately simulate type classes well in a language without higher kinds and implicits. There is the Lightweight technique for mapping the Functor onto a phantom type, but this is really a can of worms that doesn’t really work well generally. You can implement any algorithm without typeclasses or with some kludge but you really lose the entire raison d’etre of typeclasses. Maybe big corporations don’t care about how much productivity they waste as long as they can hire enough coders. Scala may never have any USP for corporations. But a stuck-in-the-mud minuscule developer pool is not helping.

If you truly believed the situation were that dire, you’d absolutely oppose this. This change was done with only token feedback from the community and has been repeatedly received pushback - not only from those like myself who think it’s a categorically a bad idea, but also from those who think the idea is good and the implementation needs work.

The only thing worse than declining to make a move because of fear, is racing after a gut feeling that lacks that data to support the hypothesis that it’ll gain more developers than it’ll lose.

How is that you misunderstood what I wrote? If I have to write the code with braces initially that defeats the point doesn’t it. You are agreeing with me (that if I accept your assertion) that if I write the code braceless, then I can not be guaranteed of a fidelity translation to braced.

Where is your data? Python has 30% market share. Scala has 0.63%. It is worth a try. And nobody who needs Scala’s unique features is leaving. If they do not need the unique features, then they were probably not staying anyway. If you need Scala’s unique features, you will not leave after all.

This appears to be the point of confusion. You can currently enable a setting in IntelliJ that automatically inserts braces when you hit Enter, if it thinks you’ll need it. So if IntelliJ is right often enough for you, then you can mostly write without having to worry about braces, other than occasionally flagging the ones you’d like to see.

On the other hand, trying to add back in braces where none exist will end up adding them in a bunch of places they aren’t actually needed, and we lose the pleasant middle ground that we enjoyed in Scala 2.

That is not my definition of writing braceless code. That is some annoying tool interfering with my rapid coding.