Brackets are awesome, don’t use them!

This is a syntax bike-shedding post, where I will try to explain why I think languages should stop using curly brackets for code blocks. I don’t expect anyone to come away completely blown away by this or anything, but I’m a language nerd and often end up discussing in-development languages with their designers. And since approximately 90% of all language discussion is about syntax, I’ll just write a reusable note on brackets here. J

Why brackets are awesome

Brackets are awesome because you can use them to group things in a way that visually resembles the contents being “grabbed” from both directions. This serves to isolate the contents visually, and allows for nesting. Observe:

((a,b),c)

How awesome is that? It’s immediately clear just visually that ‘a’ and ‘b’ belong together, and that they’re nested inside another pair with ‘c’. There are several kinds of brackets, we could use curly brackets and they work just as awesomely at grouping and nesting things:

{{a,b},c}

The reason this works is because the brackets visually look like they are physically containing any horizontal content between them due to the “grasping” nature of the brackets themselves, and the mirror-symmetry.

When brackets are not so awesome

It’s no coincidence that the previous two examples look visually pleasing, the brackets were designed with that use in mind. Observe what happens if we make a slight adjustment:

}}a,b{,c{

Ugh! Not nearly as nice! It gets worse when we flip it around 90 degrees:

Suffice to say, brackets only really work if you put stuff on a horizontal line with the brackets oriented the right way around.

This brings me how curly brackets are used in programming languages:

{
    Foo;
    Bar;
}

Here we’re really no better off than the previous example. Because the content is laid out vertically, the brackets are not oriented the right way around. The symmetry of the brackets is along the wrong axis, and they do not visually “grasp” the contents.

So is this some kind of horrible atrocity that leads any curly-bracket language to unavoidable doom? Well, no, obviously not. You learn to see the curly brackets as “start” and “end” tokens for code blocks, so the fact that the brackets are no longer awesome at grouping the content isn’t such a huge deal.

So why the fuss? Well because brackets are awesome for so many other things! There’s a ton of things in a programming language that could use a set of brackets to group and nest things (indexing, record literals, tuple literals, function arguments, generics, lifetime annotations, etc. etc.). But if we’re “wasting” one of the bracket types on vertical content then it’s no longer available for uses where it would be more valuable (unless you overload them to mean multiple different things in different context, which IMO makes things look more “samey” and cluttered - see round brackets in Lisp).

Alternatives to curly brackets for code blocks

I propose languages use simple “do”/“end” keywords for code blocks. They can be typed about as quickly as brackets, and IMO reduce the “line-noise” quality of the language. Plus, they lend themselves better to a unified indentation style - avoid the wasted lines of Allman style without spurious arguments about symmetry (since they’re just keywords, people are less likely to object to the “do”/“end” not lining up):

if (x == y) do
    printf("Foo!");
end 

For language constructs that always have a code block “hanging off of them” the “do” keyword could be implicit without introducing any ugly asymmetry. For example, these C-style constructs could all be valid even though for each code block we’ve left off the initial “do” for brevity.

for(int i = 0; i < n; ++n)
    printf("%d\n", i);
end
 
if (x == y)
    printf("Foo!");
end 

void func(int x)
    printf("%d\n", x);
end

This of course requires that each of these constructs have a clear syntactic “end point” before the code block. E.g. you could choose to get rid of the round brackets in an if-statement and make the “do” required:

if x == y do
    printf("Foo!");
end
comments powered by Disqus