I think it’s a shame that the topic of significant indentation is always so heated. I sympathize fully with Martin’s reasons for wanting optional braces. When writing code, it’s a pain to fit in braces every time you need to add an extra statement for debugging or other things.
For writing code, I think it’s exclusively a change for the better once tooling (like IntelliJ which currently refuses to indent how I intend all the time) catches up.
For reading, I’m not so sure. I’ve never understood the religious sentiment against having lines with just braces. For long methods or template definitions where it can be hard to find the beginning of the definition, most editors provide some way of navigating to the start of a brace or parenthesis. Providing support for such navigation is much more complicated in the absence of braces.
When I’ve read the Dotty code base, it’s been extremely useful to be able to easily find the beginning and end of a definition using Ctrl+M
in Sublime Text.
end
markers only solve part of the problem. It tells me what definition just ended, but that doesn’t really help me if I find myself in the middle of a definition and I want to find the beginning. I welcome an example of where it would be useful, but my spontaneous reaction is that it just adds noise where a }
would’ve been clearer. It also makes me think of languages with begin
… end
block syntax, which I personally think is very hard to read. The end
marker is also not unambiguous, as shown by this example:
class C:
//Ridiculous amount of code
end C
object C:
//Ridiculous amount of code
end C
If i now read end C
, how can I know if I’m looking at the class C or it’s companion object?
I’m also not sold on using :
for starting a block. :
already has different meaning depending on whether it’s used in a context bound, or for giving a type to an expression or definition. It could be argued that it’s easy to distinguish the new meaning from the other ones, but I remember seeing arguments (which I can’t find now) against introducing syntax like forall T. T
for polymorphic function types, because it would be confusing to introduce new meaning for ‘.
’, which is a reasonable objection.
Personally, I would’ve preferred a where
marker:
trait A where
def f: Int
class C(x: Int) extends A where
def f = x
object O where
def f = 3
enum Color where
case Red, Green, Blue
type T = A where
def f: Int
given [T](using Ord[T]) as Ord[List[T]] where
def compare(x: List[T], y: List[T]) = ???
extension (xs: List[Int]) where
def second: Int = xs.tail.head
def third: Int = xs.tail.tail.head
new A where
def f = 3
Or simply drop :
without replacement.
There are many cases where braces make code more readable and many where the conciseness of leaving them out makes code easier to write and read. Personally I think optional braces would overall be a good addition. I also completely disagree with the opinion that braces must be optional everywhere or nowhere. That said, there are details in the syntax that could be discussed more considering how big change it is and how permanent it is. It will be really hard to change once it’s been established.