Cléber Zavadniak Website

Why I’m keeping significant whitespaces in Til

Because uncertainty about style is an insidious thing. This entire article is a proof in itself.

I never actually got what was the point about the great “significant whitespace” discussion back when Python was still a new thing. In the end, you know, programmers are going to not only indent their code all the same but they’ll also get mad about others who don’t do it properly. And then the code is exactly as if it was a “indentation is scope” language, but now with curly braces or whatever.

# This is "stupid":
  def f(x):
      return x * 10
  
  # And this is The Right Way™:
  def f(x) {
      return x * 10
  }
  
  # Awesome...

(And I’ll be honest: I really like the curly braces.)

Til is not like Python: you surround SubPrograms, ahem, with curly braces. And commands inside SubCommands should be indented properly – users are not forced to (at least for now), but they should care about it. But, anyway, code blocks or scopes are not defined by how much they are indented.

However, whitespaces are significant in other ways. First, they are not allowed between a Command (that is: a NameAtom and its eventual arguments) and the end-of-line character or the end of the file. Will someone complain about that? As bizarre as it is, yes, I’m pretty sure. But I’m not ashamed: trailing whitespaces are not something “passable”. There is, I know, a whole lot of seasoned programmers who don’t really care. But I do.

Second, the language grammar is very strict — on purpose. A Program is a SubProgram followed by the end of the file. A SubProgram is a sequence of Pipelines. A Pipeline is one or more Commands separated by a pipe (|) and that pipe is separated from each command by one whitespace — the only exception being when the pipe is also being used as a line-continuation token. In that case, there can be many whitespaces between the beginning of the line and the pipe itself but, again, only one whitespace between the pipe character and the next Command.

# Okay:
  cmd1 x | cmd2 | cmd 3 y
  
  # Not okay:
  cmd1 x  | cmd2 | cmd3 y
  
  # Okay:
  cmd1 x
     | cmd 2
     | cmd 3 y
  
  # Not okay:
  cmd1 x
     |  cmd2
     | cmd3 y

Now a Command is a NameAtom followed or not by arguments, and there must be only one whitespace separating the NameAtom that represents the name of the command/procedure and its arguments list. This list, in turn, contains multiple ListItems that also must be separated one of the other by one and only one whitespace.

# Okay:
  command_one alfa beta
  
  # Not okay:
  cmd2        gama delta Whoof!

After some nice person published a link to Til Website at HackerNews, someone managed to convince me that having significant whitespaces would be a bad idea. And I agreed and decided to remove this “limtation” as soon as possible.

But now I’m stepping back and keeping the original premise and I’ll explain why.

The basic idea is: ignoring whitespaces is like opening the hell doors hoping to just get a quick glimpse and closing it fast.

That never happens this way. The demons always escape and at least one of them pursues you until the rest of your miserable life.

I’ll adapt the example I received as an argument for ignoring extra whitespaces:

# Without extra whitespaces:
  set black 0x000000
  set white 0xffffff
  set red 0xff0000
  set blue 0x0000ff
  set green 0x00ff00
  
  # With extra whitespaces:
  set black 0x000000
  set white 0xffffff
  set red   0xff0000
  set blue  0x0000ff
  set green 0x00ff00

And… that’s it. This kind of “vertical alignment of stacked things” is the reason why Til should open the hell doors.

Funny thing is: I hate this kind of thing (at the time of that discussion, trying to be empathic and a good listener, I kind of forgot this fact). This seems like a nice touch at first but very rapidly your team will start to see things popping up on diffs that should not be popping up on diffs. And all it takes is a variable with a somewhat long name:

set black 0x000000
  set white 0xffffff
  set red   0xff0000
  set blue  0x0000ff
  set green 0x00ff00
  set default_color 0x0f0f0f

And what happens next? The programmer is going to “align” the values and, boom!, a diff that should show only one different line now shows six. And that drives me crazy because when you’re draining a little bit of other programmers mental effort when they review your code.

And let’s be frank: the following code is not in the slightest “harder” to read:

set black 0x000000
  set white 0xffffff
  set red 0xff0000
  set blue 0x0000ff
  set green 0x00ff00
  set default_color 0x0f0f0f

Your eyes are not traveling around to find each correspondence.

I even take the trouble of teaching beginners to not align values because it does not add any real readability to the code and if you choose to align things you’re going to waste your precious time maintaining that for absolutely no tangible reason.

Maintaining the alignment, applying effort where none is needed, making useless things pop up on diffs… what a waste!

And I also wonder how this kind of thing would add any readability to the code:

C# code

My eyes keep traveling a lot around the screen…

What is the variable the value 20 is being assigned to, again? Wow, eyes travel! A ruler may come handy.

So, in short:

And that’s it. No extra whitespaces allowed in Til, for a greater good.

(But if you know a good example where “vertical alignment” actually makes a enormous difference on code readability, I would be glad to see. My opinion is just that: my opinion. I like when people help me to see things from other angles.)


Back to index