On braces and indentation-based syntax

Why do you need the pleonastic end map if you have outdenting to demarcate the end of the block?

My vote and prayer to the coding God is that indenting lords over noisy braces. Fix it and make it consistent everywhere, no special case exclusions.

So don’t use it if you do not like it. Everyone can choose what they like. Let’s see what the free market vote is. I can pretty much bet you that braceless will stomp all over braced code in market adoption. Python is very popular. We are getting old. I am age 56. The young people like different things.

And short indented blocks of code may dominate usage, if your argument is that braceless is more of a win if at all for short indented blocks. I liked what I saw when I was perusing the Scala.js code in the dotc compiler.

This can be dealt with the proper design. If indented blocks must be aligned on preset number of spaces per indent, then other indents can be continuations. This is how I had designed my parser for the language which I was working on. I noticed Scala didn’t make this design decision so I figured there were going to be problems.

For braceless, I strongly suggest just outlaw tabs and be done with it. Choose 3 spaces for indentation and end the problem once and for all. For braced allow tabs and anything willy-nilly for maximum craziness and inconsistencies. Let people chose their poison.

I would bet the opposite is true, that the whitespace feature of Python contributes to its popularity.

Scala has accommodated you. You can still use curly braces. If you’re the type of person who prefers inconsistent indenting, inconsistent use of tabs, and the extra noise of braces, then you have not been abandoned. But why should you force to rest of us to make your choice? Let the ecosystem bifurcate.

Can’t I just write xs.map(x => x + 1)? What’s the big deal as I find the parenthesized invocation more regular for us (non-Haskell) normies anyway.

1 Like

See my above proposal, under Regular Scala, for a reason this syntax not being accepted is an issue

1 Like

4 spaces is too much. 2 spaces is arguably more difficult for some people to parse (not me). Scala 3 should choose 3 spaces as the best compromise. If you hard-code the indentation then line continuations can be any indent not a multiple of 3. Braceless block indenting is intended to enforce a consistency that is not enforced with braced. Those who want willy-nilly style freedom can use the curly braces. I vote for enforced consistency for the braceless option and thus gain the line continuations (or is Scala able to parse the line continuations without such an enforced consistency?)

I don’t think parameters to function invocations should ever be blocks. They should be at most line continuations delimited with parentheses consistently in all cases. If you need to write a long function then given it a name and supply the name instead of a lambda.

Very long lambdas make code unreadable. Why are we trying shoehorn this weird syntax of lambdas as blocks? This is becoming gibberish and adding more special cases for newbies to stumble on.

One of the huge complaints against Scala is the unnecessary complexity. Firms have abandoned Scala because of the learning curve and inability to find enough hires.

Or if you must then maybe the proposed colon syntax to at least make it clear that some block is being introduced in lieu of parentheses or a space delimited parameter list.

These two statements juxtaposed imply “only work on your own code”.

I would rather not be thusly restricted.

1 Like

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