Writings of a techie wizard
Single Entry
Thu, 08 Mar 2012

A while back I explained why I use Python, not Lisp. However, after reading this review of Go, I realized that I left out something important, something that sets Python apart from pretty much every other language out there, and certainly from every "C-oid" language, which is all that the author of the review seems able to find himself wishing for.

Here it is, in a nutshell: delimiters suck.

Back in the old days, when CPU cycles were scarce and parsers had to be streamlined, it made a kind of sense to make the programmer do the lion's share of the work of defining the structure of the source code. Curly braces, parentheses, semicolons, and so forth helped simplify the process of parsing and compiling code, and if that made the difference between a short wait for your code to compile and run so you could test it, and having to go out and grab coffee (or even lunch) while your code compiled, that was a tradeoff worth making.

But this is 2012, for goodness' sake. Compilation is cheap. Code gets compiled on the fly all the time now; after all, web pages are code that needs to be compiled every time the page loads. And that means that any programming language that makes more work for the programmer in the name of making less work for the compiler is simply braindead in today's world. And yet that's exactly what programming languages with delimiters do. Why should I have to tell the parser that, oh, here's a new block; oh, here's the condition for an if statement; oh, here's the end of a statement? Why can't it figure all that out for itself?

The answer, of course, is that it can; but our lazy programming languages don't require it to. Except one. And that's why Python is my favorite language: no delimiters. No curly braces, no parentheses, no semicolons. None. (Yes, strictly speaking, there is one delimiter: the colon that opens a new indent block. But typing that feels natural, since the whole point is that I'm starting a new block, and typing the colon feels like I'm just starting the new block, especially since I don't need to type any corresponding closing delimiter at the end of the block. Still, if Python were to upgrade its parser to eliminate the need for the colon, I wouldn't complain.) Python indicates code structure the sane way, with indentation. In other words, it uses something that every coder does anyway, simply because it's necessary to make the code readable. Indentation requires no extra typing; I do what I'm best at, writing actual code instead of delimiters, and the computer does what it's best at, applying complex but precisely specified formal rules much faster and more accurately than a human can.

And truth be told, even those who claim to prefer other languages know in their hearts that I'm right. For example, the reviewer applauds the fact that Go doesn't require semicolons--but then says:

Well, actually there are semicolons, but they are discouraged. It works like JavaScript, there is a simple rule that makes the parser insert a semicolon at certain line ends.

In other words, the Go designers know that the parser is perfectly capable of spotting the end of a logical statement without requiring a delimiter. Then why isn't the delimiter eliminated, instead of just being "discouraged"?

But wait; it gets better. The next comment we get is this:

Next in category "pure heresy": Go defines a canonical indentation and the One True Bracing Style.

In other words, the Go designers also know that indentation is important; yet they still cling to the delusion that somehow the indentation needs help from curly braces. But if you're going to define a One True Bracing Style, why can't the parser simply deduce where the braces would go, the same way it can deduce where semicolons would go? Well, the reviewer says this about the canonical indentation style:

Like Python, only I think python has a tad too little visual cues. Indentation alone isn't always sufficiently clear, so we get to keep our beloved braces.

Oh, so the braces are to help the programmer know where the ends of blocks are? Strange how so many people are able to program in Python perfectly well without this crutch. Of course, if you don't have a canonical indentation style, you can't depend on it as a cue, so you may have problems with indentation being "sufficiently clear". But the reviewer just told us that Go does have a canonical indentation style! I think he hasn't fully grasped the implications.

(An aside here: the Go designers are making a huge mistake with the canonical indentation, by using tabs instead of spaces. Of course, all Pythonistas know that indenting with tabs is just a straight road to perdition. See here and here for the details.)

There's another funny bit in the next item in the review. We read this...

Speaking of braces, there are no brace-free forms of if and loops.

...followed almost immediately by this:

One important technical reason for the previous point is the fact that those control statements no longer have parens.

In other words, take away parentheses around conditionals (good), but then use that as an excuse to keep curly braces (braindead). Give with one hand and take away with the other. But wait; there's a reason:

Only Perl6 tries to parse paren-less if without curlies, and we all know how complicated Perl parsers used to be (and obviously, still are).

I guess the reviewer forgot that Python has no trouble parsing paren-less if without curlies. And without forcing you to use Perl and its parser, either.

Static Typing Sucks Too

Since we're on the subject of Python vs. "C-oid" languages, I'll go ahead and rant about variable typing as well. The reviewer notes that Go is smart enough to use duck typing, as Python does, instead of requiring explicit interface declarations:

Go uses interfaces exclusively. Unlike Java, however, you don't declare that a given type conforms to some interface. If it does, it automatically is usable as that interface.

Great! Go objects are duck-typable. But that raises the obvious next question: what about references to objects, i.e., variables? Well, that's better than C, in that variable declarations don't require explicit type specifiers:

If you leave out the type, the type is instead taken from the assignment. You may even leave out the declaration altogether by using the new declare-and-initialize operator.

Okay, good. But once you've done that once, you're stuck; the new variable declaration syntax

does not introduce dynamic typing, it does not allow changing a declared variable's type, it does not remove the need to declare variables, it does not allow you to declare variables twice. It's really the same as before, semantically, but much lighter on syntax. Feels like an ad-hoc scripting language but still gives you the benefits of static typing.

Um, what benefits of static typing? Objects are already typed; once you create an object, its type is fixed forever. That's true in every language, including Python; I'm not sure I can see how you could implement an object system at all without it. That, plus duck typing, ensures that if you try to do anything with an object that it doesn't support, the language will tell you. If you want anything more draconian than that, you don't want a language like Go, or Python, or C for that matter. You want something like Visual Basic, because you're going to let people use it who can't be trusted with fully capable tools.

But given that you're cool with duck typing, whyinhell would you want to restrict variable bindings? When you reassign a variable, you aren't changing the type of its object; you are binding it to a new object, which has been freshly created, and of course when you write the code that creates it, you have already decided what type you want it to be, just like when you bound the variable to its original value. Sure, the vast majority of the time, the new object will have the same type as the old; but what about those cases where you don't want it to? What if, for example, you want to assign a new object that is duck-type compatible with the old one, but has no common base type with the old one, so the type system can't tell they're compatible? Again, if you want your type system to prevent you from doing this, you don't want a fully capable language in the first place.

I could go on about other stuff, but I think I've said enough to make it clear, once again, why Python is my favorite language. Frankly, the only advantage I can see with Go over Python (and not just based on this review; I've been following Go's progress for several years now) is speed; but Moore's Law and projects like PyPy are making that less and less of an issue every day. It's great that people keep on trying new things with programming languages, but at least this time, I'm sticking with Python.

(Update: there is a discussion of this post on Hacker News.)

Posted at 23:28   |   Category: rants   |   Tags: computers   |   Permalink
Wizard Projects
Site Links
Open Source Projects
dev release
dev release
dev release
dev release
dev release
dev release
dev release
dev release
dev release
dev release
dev release
dev release
dev release
dev release
Old Open Source Projects
Python Recipes
Fun Stuff
Shameless Plugs
Copyright © 2011-2015
by Peter A. Donis
All Rights Reserved