Feedback sought: Optional Braces

It absolutely can have a good result - the problem is that it takes something we currently get basically for free, and moves it to a space where we have to spend time and money to get back to the level of “good” we currently enjoy.

When trying to sell a team on upgrading to Scala 3, that additional cost is absolutely a problem, regardless of the eventual outcome.

2 Likes

Software comes with an implicit promise of continuous improvement (or it’s dead), and artificial languages are software. So taking the cost of change is inevitable. You think you will have difficulties convincing your team that this change is worth it. Well, my experience is that readability gains win over the cost of change in the long run.

My hypothesis is that if you go for a pragmatic coding standard along with option 3 that allows for sensible a mix of braceful and braceless code, you will win in productivity in the long run.

I would actually be rather comfortable with the challenge to stand in front of a skeptic team and be very enthusiastic about the general improvement in readability and ergonomics of the braceless style. (I was a skeptic myself in the beginning…)

I agree with this, and happily I’m currently in one of the most progressive-minded engineering teams I’ve ever had the pleasure to work with - but we also don’t tend to adopt things that don’t pull their weight. Making the case that the upgrade to Scala 3 is worth it is something I’d have to do, even if the team wasn’t blended recently with a non-Scala shop.

I guess the biggest difference is that I haven’t been convinced this is actually going to improve readability, so I’m dreading this being brought up because I’ve got literally nothing to defend this with.

  • I can’t say, “here’s the research that points to this increasing readability or productivity,” because it doesn’t exist.

  • I can’t say, “I’ve tried it, and found it to be an improvement,” because when I tried it I found it much more difficult to work with, and the sample code I’ve seen has been difficult for me to read.

  • I can’t say, “this was a broad ask from the community,” because this came into being and is going in largely because Martin likes the idea.

  • I can’t say, “this has broad consensus in the community,” because if it did, this wouldn’t be at 500+ posts yet.

“Some people like this” is about the best I can do, and that’s really not going to be very convincing when compared against the upgrade cost.

4 Likes

Yes, more research is needed, but there is actually a bulk of research on program comprehension and there is at least some indication that we understand line by line in chunks, which indicate that conciseness may be a factor that speak in favor of braceless. See for example this recent ESEM paper with a summary of current literature: https://arxiv.org/pdf/2007.12520.pdf

So you can say that there are indications in program comrehension research that suggest that we understand code in chunks and snippets and the new Scala 3 syntax provides “tighter chunks”.

Also, I think you should try it out some more :wink: as there are many (not just “some”) who are witnesses of great pleasure with the ergonomics of writing and increased readability after a while of practice with the new control syntax in combo with breaceless.

An idea: perhaps you can find a champion within your team who can try it out in depth and then report back to your team about the gains of the totality of changes in Scala 3 and not just single out this sole feature?

I don’t see the length of this thread as a measure of non-consensus in the community, but rather as a proof of us here being engaged (and both you and me are guilty of boosting the number of posts :blush: ). To say something about what the broader community thinks we need to get this out in the wild and then do scientific surveys (which is a hard job in general).

1 Like

One of the things I would have liked is if this additional research had been done before upending the standard style. While conciseness may be a factor that speaks in favor of bracelessness, lack of clear boundaries between chunks may be a factor that speaks against it.

Been there, done that, and it ended up killing my enthusiasm for a tool that I’ve wanted to write for literally years.

I can’t understate how difficult I find this style to read. It’s an experience I’ve found very similar to descriptions of dyslexia - only instead of the letters jumping around, it’s the block’s associations with each other.

I assume you mean well, but I’m getting really tired of being told, “try it a bit more, you’ll like it eventually.” It comes off as, at best, extremely condescending. I have tried it, and it’s only gotten more unpleasant and difficult to work with the more time I spend with it.

Problem is that, normally, that guy would be me. If I’m not the one championing this, there are going to be questions about why not, and I don’t have any answers that would help the situation. Overall, I like the vast majority of changes, however this has the potential to touch nearly every line of code, and I find it so deeply unpleasant to work with, that it weighs very heavily on the balance.

3 Likes

I’m sorry if I offended you and I did absolutely not intend to sound condescending. If you find braceless bad then there is at least the nicety that they are optional, those braces. And I guess there will be many teams that will stick with braces.

I’m very glad that we get the braceless style in our palette as I find it easier to read and so seem many of my students at a glance, but I will know more about how learners find Scala 3 in the fall semester, when my course starts again. (Off now, bed time soon.)

I figured, and don’t worry, I’m not offended so much as exhausted

1 Like

It is a good joke, I am very engaged how much will it cost for upgrade, and How long am I going to wait stable ide which allows me to work as comfortable as I can do right now.

It is very ironically that so much people try to prove that readability is better in significant indentation but if it is so, why the pycharm has so many warnings in python that force to insert spaces between classes and methods. Why a scala formatter helps me to write code and a python formatter can only help me to insert spaces.

2 Likes

I think you might be overselling the importance of this syntax.

Inlining, type computations, givens, and TASTY are going to be the things that really make a difference. Writing code that performs well will be more practical with inlining. Type computations will allow straightforward code that previously required great trickery to pull off. Givens will not simplify inlining, but will smooth over the rough edges (e.g. needing to name something when that’s just an implementation detail). TASTY will make manipulation of the logic (and the source code) of the program more approachable.

I don’t think this is necessarily even the biggest change to syntax. @infix is going to absolutely clobber my code, making it vastly less regular. The plan is that there’s nothing I can do about it.

With :, there ought to be auto-formatters that can fix the style to whatever is needed. Because of its nature, you’ll automatically get reasonable-looking braced code (unlike with infix, where vertical alignment may get messed up due to two spaces turning into three other characters). Yes, maybe it will take a little while to set a policy, but if the policy is “don’t do it”, that’s easy; and if it’s something else, it should be easy to fix if you change your mind once the tooling catches up.

3 Likes

It’s going to depend a lot on how your code looks, and what’s easy or hard for you to read. @infix will have almost no impact on the code I interact with on a daily basis (mine or otherwise).

On the other hand, for me this change has the potential to significantly impact my ability to read Scala 3 code, which means it has the potential to make the other changes completely irrelevant. A beautifully written poem might be easier to write in Latin, but that’s kind of irrelevant to me if I can’t read it :man_shrugging:

2 Likes

Well, formatting tools won’t help you work with others’ code in places with minimal support. However, given the profusion of editors with multiple insertion points these days, it’s not out of the question that you could get some pretty nice (or at least blatant) colorization to help see indentation level.

Would something like this work for you, or is this equally hard to see:

(taken from an example by Dean Wampler, with me applying colorized columns as indentation guides).

1 Like

I agree. After writing a fair amount of indentation-based code in Haskell and Python, I found it hard to go back to other languages that require a lot of braces and parentheses. IMHO, once you’ve had the experience of not using those for weeks or months, when you go back to C/Java/Scala2, you realize how much “noise” they add to code.

1 Like

@odersky Many, many posts ago you mentioned the possibility of having “clearer rules for end-markers.”
What did you mean?

How about the font size shrinks by a point for each indent?

Or highlighting bumps down in intensity; when a line is longer than the right margin, it turns invisible.

(Edit: probably I won’t respond to exhausted replies.)

If you google “dollars to donuts”, it doesn’t give you a conversion factor as with other units.

1 Like

I wasn’t able to tell from that example (not enough nesting), so I tried to apply the same principles to an expanded version of some code I posted as an example of something that was hard to read.

The results were a bit mixed. I had to use the a darker in place of the lighter in your example (I had trouble differentiating the colors), and I made a version using Dark Mode, as that’s closer to what I generally use on a day-to-day basis.

It’s definitely an improvement over the the thin lines that normally get used, and it’s fairly readable (though “blatant” is a good descriptor).

On the other hand, the braces version is only 5 lines longer, so it seems like a lot of hassle for minimal/subjective gains:

class Foo {
  type F[A] = Either[List[String], A]

  def foo: F[Int] = {
    def ensureA: F[Int] = 
      Right(3).flatMap { x => 
          if x == 2 then
            Left("Fail" :: Nil)
          else
            Right(3)
      }

    def ensureB: F[Int] = {
      val base = 2 match {
        case 1 => Right(2)
        case 2 => 
          Left("Opps!" :: Nil)
        case _ => Left("Jeepers!" :: Nil)
      }
      base
    }

    def ensureC: F[Int] = {
      def double(i: Int) = i * 2
      Right(2)
        .map(double)
    }

    for {
      a <- ensureA
      b <- ensureB
      c <- ensureC
    } yield baz(a,b,c)
  }
  
  def baz(a: Int, b: Int, c: Int): Int = a + b + c 
}

On the bright side, while it would require building a plugin, it does get us to ugly-readable instead of painfully illegible, so that’s an improvement :+1:

1 Like

Dude, do you make fun of people in wheelchairs too? Seriously, read the room :roll_eyes:

1 Like

I think I was in the same boat (skeptical about end marker) due to Ruby :slight_smile:

I agree that just replacing } with end gains nothing and is just more verbose.

What makes a difference is end MyDeclaration. That and the fact that it’s not mandatory, which means that you only have to use it when you think it’s needed.

I expect that IntelliJ will provide a shortcut to switch between styles so it’s easy to try what feels better.

Honestly, I don’t think you have to sell each and every individual feature of a language to an engineering department. The value of a language comes from the aggregation of features, libraries, community, culture, etc. Thus, when a decision is made to go forward, it is because it is believed that overall, the benefits outweigh the downsides (and every language has some features that people don’t like for one reason or another).

4 Likes

Overall, I agree with this - but there’s a big asterisk that the weights of those features are not going to be equal, and this one is going to open up a dialog that showcases the worse parts of Scala - and I can’t see any way to avoid this.

I can’t advocate for something that’s going to result in a worse experience, so until the tooling is in place, I can’t recommend upgrading. Because I have a consistent pattern of promoting Scala, and advocating for the adoption of libraries like cats, this is going to raise some eyebrows at my job, which will lead to a discussion of the primary reason for my objection: Optional Braces.

I don’t see a way to have that conversation and avoid touching on why it exists, which touches on some of Scala’s biggest perceived risks - backwards incompatible changes, perceived unnecessary complexity, and endless style bike shedding. In fairness, most of those haven’t been an issue for a while, but trust is hard to earn and easy to erode, and the lack of process makes it infeasible for me to provide assurances this won’t happen again.

This would still be an issue under normal circumstances, but blending companies makes everything so much worse - bad impressions spread more easily than good, so while I’m going to have more difficulty advocating for Scala, it’s not really going to be any more difficult for my reservations to propagate.

It’s an unpleasant situation to be in. On the one hand I want to be able to continue to use Scala, and I think that switching would be a big improvement for the part of the company that’s been stuck with Java. On the other hand, an honest answer to, “What do you think about upgrading to Scala 3?” is going to cause damage I don’t think I’m going to be able to mitigate, and it’s going to be asked.

3 Likes

I meant linter-enforced rules for when an end marker should be used.

My current approach when to use an end-marker has evolved a bit from the start. Originally, I thought an end marker was desirable if it closes a scope that is either long (say,15 lines +) or heavily indented (say, 4 levels +). Now I usually just follow the rule to use an end marker if the preceding scope has blank lines. Long scopes are usually broken up with blank lines anyway. And heavily indentented scopes are not a problem if they are not at the same time long.

It seems a bit odd to me to dismiss all previous arguments in favor of with because of 1 single use case where : actually works well (which is methods with a single by-name parameter), which currently requires a -Y compiler flag, and where with would not even be the alternative.

5 Likes