Make "fewerBraces" available outside snapshot releases

Time to rename Scala 3 to Jambalaya.

Since I tend to add end markers, I wondered if that is my end marker, and git blame says yes.

So I can attest that this is not a high quality for a style test, as it shows me learning Scala 3 during the pandemic. The closing brace is “legacy”, as it is not usual to format the entire file when making an edit.

On the Dotty project, I have encountered the pushback that “this edit is not minimal”. So even my sense of a good compromise does not meet everyone’s standard.

I have recently come around to arranging my dots vertically instead of horizontally in “fluent” style. I previously thought of vertical as Java style because it’s the verbosity that requires it. I think I switched because of using less infix (although leading infix improves vertical infix), and now I would be willing to follow anyone’s lead in using indents of 3 or 4. Probably 3 just to remain different from Java. Oh, and 3 because it’s Scala 3.

2 Likes

“Mess” is also a food word for melange or mixture. Or actually, my high school Webster’s says it is just a course (of a meal), with the same root as message. It doesn’t explain why it means opposites: laying out a meal is an arrangement, and getting everyone to table is perhaps as large a task of assembly. The mess is the remains afterward.

One meaning is “enough” food: “a mess of peas” is a measure of what suffices for supper. In one of Joyce’s Dubliners stories, a fellow pops in and orders a plate of peas. That sounded so strange to me, to order peas. It doesn’t say if he ate them with a fork or spoon, or a knife coated in honey. I guess it would say if it were a honey-coated knife.

The dictionary entry directs one to “smite” and then “smegma”. TIL “smegma”. I would be comfortable saying Smegma 3 for Scala 3.

The food word I was thinking of is “hash”. That word means “ax”. I think of a “hash” always as a “re-hash”. “A restatement of something that is already known.” A hash code is such a restatement. As food, I assume a hash is something leftover, chopped up and added to the pan with some primary foodstuff. Fried potato at breakfast is a hash brown.

As a bonus word, the closure in the car port is called a hasp. I don’t know if I knew exactly what a hasp was. But if I were to come up with a hybrid of Haskell and Lisp, it would definitely be Hasp.

Edit: So my point is that I see it as a mess only in the sense of “a mess of peas.”

1 Like

That example needs some context to be understood properly. In dotty we made the decision NOT to reformat globally to indentation in order to keep meaningful git history. But every new or changed piece of code uses indentation style. For people used to the codebase that’s actually an advantage since it gives you a sort of archeological layering of code :wink: . Anyway, I would not treat that as typical.

Generally feedback on indentation was very positive so far, so there’s no way we would go back to braces only.

The issue here is that what you described sounds very typical. Basically all my OSS codr, and all the proprietary code I work on, we have a lot of old code and want to preserve VCS history. I imagine that is the same for all the Scala projects in existence today. What then?

As we’ve seen from @som-snytt, best practices around “minimal diffs” contribute to the mixing, as even working in a file for months you won’t have a consistent syntax. And lampfl/dotty is not special: we have similar “minimal diffs” conventions in all my com-lihaoyi projects, as well as my company’s codebases. Far from being special, what you describe about Dotty sounds like the most typical codebase imaginable.

I don’t mind if we need to put some work to have a smooth migration, but what I’m seeing here is “(a) ruin your git blame, (b) give up your PR best practices, or (c) live with a hodge-podge of syntaxes” as the current migration proposals. I’m sure you can see that is rather offputting and a disincentive to migrate.

What I proposed above is to do aggressive migrations to a single new syntax. That avoids (b) and (c), and we can use Git’s --ignore-rev to mitigate (a). Together with fewerBraces, that will give us files with a nice python-like syntax. And as community leaders, it is on us to come up with recommendations, so people can smoothly migrate without re-inventing half-baked migration strategies themselves.

Anyway, I’m here because we have a few million lines of Scala we may have to migrate at some point, and I want to talk about options and possibilities. I don’t want to re-litigate old decisions. I just hope others are open to engage with me on these topics as well

4 Likes

Yeah this didn’t exist when we made the decision to avoid a bulk rewrite of dotty, but nowadays it is even supported by github (Ignore commits in the blame view (Beta) - The GitHub Blog), so that decision could be revisited.

2 Likes

I was against that for indentation in general, and I am still against that. This essentially proposes trading vertical space (braces) for horizontal space (more indentation). The latter resource is the scarcest, so this is entirely the wrong trade-off!

You can get that regularity with braces as well, if that’s really the important thing:

abc
  .map { x =>
    ...
  }
  .toSet

It does use one more line, though.

While I agree with your point about indentation versus braces, IMO presenting end markers as a third option is misleading. end markers are a part of the indentation-based syntax. They provide a visible ending to larger pieces of indentation-based blocks. They even provide some added value compared to braces, in having a compiler-checked repetition of the name of the thing that is being closed. They are extremely helpful in an indentation-based codebase that exceeds one screen of vertical space.

5 Likes

I hate end markers so much. I wish they were not introduced. The convention could have been “if the block is too long, use braces”. There are automatisms in every IDEs for these. For instance in vi you can jump to the closing brace with %.

Further, I do not see the problem with mixing styles (indentation + braces). In Java/Scala2 you can already omit braces for single line blocks and nobody complains.

7 Likes

At least for me, the Java/Scala2 brace omission works because they are limited to single expressions. It’s much easier to parse with when you don’t have to deal with potentially jumping a visually indistinct number of scope levels whenever there’s a line break.

Very different situation.

1 Like

I agree with sjrd and rjolly except when I don’t.

Now (2022) I think if horizontal space feels scarce, it’s because the lines are too long. Adriaan duped me into 140+ width lines, on the theory that monitors are wider. But when I read a novel, I need a certain line length that is sustainable.

Previously, I did not like // end comments, but now I love end markers. The convention is, if the block is too long, use shorter blocks. But if you have a few local methods, with a // begin comment (because there is no begin marker yet), the end marker is indispensible. In 2022, a tool that can match braces can also match end markers with the corresponding definitions. I, too, have an overpowering nostalgia for “That '70s Tool”. But I don’t want to be constrained by it.

I would like to boost sjrd’s signal that end markers (and also optional braces) are optional. I appreciate the docs, which stage the feature as, first let’s check whether your indentation looks OK. Then, since we’re already doing that, you may omit braces. Then, for purposes of visual acuity, you may add back an end marker (albeit tastefully). Therefore, indeed, these are not separate features but of a piece.

The other style issue which goes back to time immemorial is what’s the optimal length for method definitions. Odersky says to name things but complained when my named expressions were too fine-grained. I started programming with C routines under about 200 LOC in a file. Now I prefer to contemplate only LOC that fit vertically on my screen. We should refer to “scroll-less coding”. Other dubious conventions include ordering definitions by access modifiers. Another rule that annoys me is that overloads must be contiguous in source. I would agree that overloads must be visible on one screen.

It would be wild if Scala’s name binding, which is sensitive to compilation unit, also respected what is on the screen. That is, I don’t want to be surprised by definitions in other files. What if I also don’t want to be surprised by definitions not on my screen?

Minimally, if the REPL now lets me view units of “lines that parse”, then my programming tool should also show me just the region of interest.

“Old” doesn’t mean “outdated”, we still drop a . at the end of sentences, and it’s “That 7th Century Tool” :wink:

Punctuation has stuck around because it’s useful, and as much as some limited parts of a codebase may benefit from looking like concrete poetry, I’d caution against expanding this particular experiment until it’s had time to bake and we find out if it’s actually as readable generally as it’s advocates promise, if the “cure-all” tooling that keeps getting mentioned actually materializes, etc.

I just want to put in my vote that significant indention is pretty ugly and unreadable, but I am happy that it has been included since I think it will help Scala stay relevant in this increasingly Python-dominated world.

I don’t mind many flavors of Scala, and I quite liked that Scala permitted e.g. infix and postfix ops, but that teams could decide not to permit them (or permit them in limited cases) using scalafmt, which helpful rewrites uses away if you ask it to. However, Scala 3 has taken the opinion that the language itself should participate in style enforcement, requiring infix and import postfixOps to continue to make use of them. This seems reasonable to me, because it is in the direction of code syntax that is less magical, ambiguous, and confusing.

Reading this thread, I’m worried that Scala 3 is trending in the other direction for significant whitespace: having the language encourage or even enforce the magical, ambiguous, and confusing syntax you get from significant whitespace – snippets like xs.map x => x + 1 trigger the same worries to me as ys concat xs map f, which is legal Scala 2, but I believe now generally looked down upon. I can’t tell you how many times I’ve gotten lost trying to parse multi-line nested for comprehensions in Python, though of course you can’t put all the blame on significant whitespace there. I similarly find the whitespace-heavy Haskell to be a huge pain to read.

All that is to say I sincerely hope that the plan is not to actively encourage or enforce the parenless syntax, so that those of use who don’t like it can set a flag in scalafmt that wipes it away and continue to love the language as much as we do. And if the language does want to participate in enforcement and not outsource to scalafmt, then I hope that it is in the direction of preferring the braces (i.e. requiring import language.fewerBraces, even if it graduates out of experimental).

3 Likes

I only have a hundred thousand and change, but same deal. Would rather migrate to a uniform community standard than contribute to a hodgepodge, even if nobody but me is looking at my style of Scala.

The awkward part is that although our Scala 2 code looks fairly similar (only fairly), since Scala 3 has more options, it’s likely to diverge increasingly much.

My personal rule has been: in conditions where the braceless syntax works well, use it. Otherwise, if it’s even a little questionable, don’t. This is basically the same view I use with dot-free style: use the simplicity only when it is a significant improvement to clarity.

So, for instance, I’m totally happy rewriting

def something(a: A, b: B): C = {
  val d = f(a, b)
  makeC(d, d, d)
}

as

def something(a: A, b: B): C =
  val d = f(a, b)
  makeC(d, d, d)

It’s just plain better. No downsides. Just like I’ll write xs.map(_ drop 5) instead of xs.map(_.drop(5))–the second adds a lot of visual clutter without clarifying anything whatsoever.

(In practice, “only when better” has tended to mean that I never use : to open a block. The just plain better cases almost all have an opening symbol.)

If I were to instead to try the all-in approach you suggest, the existence of unsolvable problems is, well, a problem. Code is already hard enough to understand in those kinds of problematic cases; that’s one of the last places where any loss in clarity is acceptable. The reach of what was clearly a syntactic win could be extended, though.

Note that anything that requires 4-space indents I would probably consider a non-starter, because I have plenty of code indented too many levels for 4-space indents to be viable. The level of rewriting required to lower the indentation needed exceeds what I’m likely to want to do for anything complicated enough to have needed such indentation in the first place.

5 Likes

Trailing comma is an unfortunate victim of the fewer and fewer braces movement.

I wonder if we can reinstate trailing comma before end markers?

Scala code often has a lot of indentation levels because of nested methods and objects, ifs, pattern matching, and especially higher order functions. With 4 space indentation you would need a second screen just to see the most interesting part of the code, which is usually the most indented.

5 Likes

My own two cents on this. I’m not a huge fan of indented blocks (I’ve written more Java and XML than Python and yaml), but I’ve grown to like it in Scala. I find that 2 spaces are not enough and 4 are too much waste. I’m just finishing a book in which I’ve indented all the Scala code with 3 spaces.

I don’t know how much more braces I want to see removed. Like someone said earlier, at some point it’s fanaticism, and makes code harder to read.

Still, I’m a bit annoyed when I change:

for (_ <- 1 to n) do
   blah
   blah

into

n times {
   blah
   blah
}

or when

def f = 
   blah
   blah

becomes

def f = synchronized {
   blah
   blah
}

Even if it doesn’t save a line, I’d prefer something like

def f = synchronized:
   blah
   blah
end synchronized

to the version with braces. It makes it clear that the body of the function is synchronized, arguably more than with the braces.

1 Like

As much of the discussion has been centered around professionals and legacy code, I’d just like to add my experiences from teaching one semester with Scala 3 and optional braces.

It is very salient that beginners with no previous coding experience (around 30% of my students) find the indentation syntax much easier. The ones with prior coding experience in C-like syntax have a period to adopt but almost all embrace the new syntax after a while. The ones that come from Python have a smooth transition.

I think that the colon is very intuitive and works very good as indentation marker, and in general students find it intuitive.

They tend not to use end markes spontaneously, but I asked them about code on my slides and most seem to think that nested structures get more readable with an outer end marker.

6 Likes

@odersky @sjrd I’d very much like to see fewerBraces available outside nightly, so I can use that in my teaching using stable releases. Is it possible to be included in the 3.2 series?

3 Likes

There is already a PR for it, but it was pushed to 3.3.0-RC1 milestone which will probably see light of day at end of 2022.

There was discussion of SIP meeting approval requirement, but other changes to the languages get merged without it, so I don’t understand where things are. And I don’t understand where things are with SIP meetings in general. It has been literally years since the latest one.

1 Like

I find comments like this somewhat troubling.

An unpleasant truth is we kind of suck at teaching CS and Software Development to students who do not fit a particular profile. This is understandable, as this is still really new, and in comparison to how long it took us to figure out how to teach skills like geometry and algebra to those who do not have an inclination towards those subjects, we’re doing ridiculously well.

That doesn’t change that, at least as recently as when I graduated in 2013, it was an open joke (and source of much frustration) among the Professors and TAs that CS 201 (the algorithms course) was less a class that effectively taught algorithms, and more a filter to eliminate the roughly 50% of the students that weren’t inclined toward the subject.

Python’s syntax has always been controversial, and I would hope that between all the archived threads trying to hash out how the Python community feels about it, and the discussions on this forum, it’s clear that, for at least at least a segment of the population, code without punctuation to delimit scope is not simply something that we can “get used to.” The degree to which this is met with a dismissive, “get used to it, or just do something else,” is also particularly worrisome.

There’s a chronic shortage of developers already, and maybe the solution to that is code that eschews punctuation in favor of indentation - but the introduction of this sort of change should be done with deliberation and be based on evidence rather than gut feelings, because telling students “don’t worry, you’ll get used to it” is a good way to push someone out of a CS program if it’s something they can’t get used to. And if we’re going to write these people off as acceptable losses, we’d better be really certain the change is going to bring in more people than it pushes away.

The same argument applies to Scala mindshare among developers, but at least there we’re just shooting ourselves in the foot, rather than our entire industry.

1 Like

@morgen-peschke Note that my experience regards teaching with optional braces as in Scala 3.0 and not with fewerBraces as in nightly (sorry if this was unclear in my previous post). I thus “extrapolate” the usefulness of fewerBraces from optional braces, but it is entirely my best guess and not based on empirical evidence (but for optional braces I do have empirical observations, that make me pretty sure that optional braces work better for a vast majority – where we start with braces to explain the concept of local scope and then drop them similarly as we do when explaining the use of semicolon and what a multi-line statement is etc… This way of teaching local scope by actually starting off with an explicit token is something you can’t do with Python if I understand it correctly. The braces help to initially understand the concepts of scope etc as you learn about it, but as they take up speed almost all students seems to prefer to skip the braces).