From: andrew cooke <andrew@...>

Date: Sat, 9 Jul 2011 20:30:15 -0400

Go (the programming language) is no longer new. But I don't know of a good explanation for the ambivalent reactions to the language. So here's my take. Go is very much the child of its parents (the people who brought you C). And it's clear why some people (who typically have programmed in C, Java and Python) will love it, while others (from a more academic background, who know Haskell and Scala) will feel it's an ignorant failure. Both groups have their points - it's a pity that the language couldn't have combined the practical experience and good, simple taste of the designers with some more "theoretical" ideas. Instead it's hard to avoid the idea that it's a language "proud of its ignorance", and that it suffers as a result. On the other hand, what's the alternative (clue: FS)? OK, so first I'll describe what Go is, and WHY IT'S SO GOOD. Duck Typing Go "makes duck typing static" - anything that contains the required set of methods implements the interface (even if the person writing that code had no idea the interface existed). So it combines (much of) the flexibility of Python with better checking of types. It also has a simple form of local type inference, so that you don't need to specify types where they are "obvious" - only on the arguments and return types of your functions. This helps make the duck typing more efficient - method resolution is "pushed back" to when the interface first appears, and does not need to be repeated on every use. Given all that, you might think that Go is "object oriented". And it is, in a sense, but you don't have "proper" inheritance. Personally, I don't think that's a problem. Memory Management Memory management frees you from worrying about who "owns" a reference. And in a C-like language that's a huge deal - it opens up a whole world of possibilities: first class functions, closures, continuations... Java should have exploited this, but if you compare Go with Java, it clearly comes out on top: first class, anonymous functions, with closures (coming in Java 8, honest). If you have experience with functional programming, but need to write the kind of low-level code that has traditionally been C's domain, this is awesome news. And if writing "low level" code with managed memory seems like a contradiction, you may be underestimating Go - it still has "new" and pointers, so you don't lose too much control, but you gain a pile of flexibility. This is a big, big win over C (and Java). Lightweight Threads Go also supports lightweight threads (these seem to be real threads, not coroutines). It also has a channel abstraction (think CSP) that, when you first see it, might have you thinking "oh, cool, Erlang" - but it's not; everything is inside a single process. So this is a nice interface to local threads, but nothing more. So Go is C with memory management (Java really did help the world), a cool take on Python's types, and local threads. A modern C. Everything that Java and C++ failed to be. Small, elegant, powerful. And that's great. Really. It rocks. It's not a hugely ambitious language, but if this is the next mainstream programming language then we have progress. More impressively - it can be the next systems language too (for some definition of "system"). And it's *way* easier to use than C++. In a world that knows about Java, C, Python, C++, this is one more step in the right direction. Excellent. Second: so, WHY DOES IT SUCK? To understand that, you need to understand the academics. There's a lot of research done on language design these days. It's big (university) business and it's making real advances. Largely because it's found a "scientific" way to approach the subject. Imagine when physics was just starting to get off the ground. Back when people were discovering electricity, for example. Everyone was like "hey, there's this cool trick I can do with the skin from a dead cat and a glass rod!" "A dead cat?" "Yeah!" Which was fun. But then maths got involved and we began to see the underlying connections - the patterns, the regularities, the way that light and electricity and magnetism and radio waves are all interconnected. A systematic, mathematical approach connected a wide range of different ideas. And we gained from that. Radio, TV, microwave dinners. Computers, even. The same thing is happening with programming languages. Mathematical ideas unite different parts of languages. When you spot those ideas you can join together "different bits" to give something more uniform, and more powerful. Go ignores all that. You don't need to understand the maths to see this in action. You can see that things are not well thought out just by looking at the language. Take functions. Functions are cool. Read an intro to functional programming. First chapter, you're going to be recursing. Sure, when you start, it's a little confusing. But then it "clicks" and you see how it can help you make programs cleaner. And it feels good. Boy, does it feel good. We've known this for years. Functional programming languages have hammered out all the tiny details. It's easy to get this right. It's easy to implement. Yet Go fucked it up. Not in a big way, sure, but it's the details that count. It turns out that, in Go, you can't write a self-recursive anonymous function - there's no way to make it refer to itself. Well, you can do a dirty hack that's the "official work-around" (I'll let you google for the bug report). But how could anyone, in this day and age, get that wrong? What were they thinking? It doesn't stop there. You can't use recursion much anyway, because Go doesn't guarantee efficient tail calls. Which, again, is just dumb. There would have been no great implementation cost - so simple ignorance means that you can't use Go to write code in a certain style. I'm not saying that style is always good, but I'd like the choice. It's like being in a workshop that only has hammers... Another example. The "academic" approach looks for patterns. It tries to reduce the language to a few simple, elegant ideas. An important result of this is that you, as a programmer, become as powerful as the language designer. What do I mean by that? I mean that by exposing the "deep" ideas there is less "magic" that only the language implementation can do. A good example of this is continuations. Continuations let *you*, the programmer, implement exceptions. Or functionality like Python's "yield". So someone can build a language that contains continuations (whatever they are - the details don't matter here) and then "for free" the programmer can "extend the language" with features that other languages have built in. Now, continuations are, arguably, hard-core. No-one is criticising Go for not having continuations (well... now that I ask, why doesn't it?). But that's an example that illustrates the related "design smell": if the language is doing things that you, as a programmer, can't do, then it's likely not a well-designed language. And Go does things that you can't do. There's this little command called "make" that does some weird magic. It's like "new" but does extra stuff. And you can't extend it. What? Or: you can only use certain types as hash keys. The same bad smell: some types (known to the system) behave differently from the ones you, as a programmer, make. Why? By now you're starting to get suspicious. So you start asking yourself: what else have they ignored? And you look at the type system. And it's kind of flakey. A decent modern type system guarantees no run time errors. Not Go. And the "comma OK" pattern? Isn't that a broken version of the maybe type? Oh, I guess Go doesn't use that because it doesn't have pattern matching. Well why not? The list goes on... Now some of the above objections can probably be explained by efficiency. And that's a good excuse. It's important to make a better C. Believe me - I've been programming in C for the last month. There's another big reason: Style. Go is a stylish language. It's not necessarily elegant, but it feels right. Despite all the above, it's simple and understandable. You know you can use it to get the job done. But wait! Surely an academic, elegant language should be simpler still? Those "deep" patterns should make things easier! Yeah. You'd think so, wouldn't you? But go look at Fucking Scala. Yup. Need to wash your eyes out with bleach? Thought so. Fucking Scala (that's the official language name, I believe) is the best argument I have that Go's creators know more than the academics. So is that it? Is there really no better compromise? Do we have to choose between Go and Fucking Scala? You would hope not. But network effects are more important than technical chops. I can live with Go. I couldn't live with Fucking Scala. Sure, I'd prefer Haskell, ML, or even a decently typed Scheme, but they've already lost. All we can ask, then, is how to avoid this in the future. Next time someone with style and clout sits down to write a language, how do we make sure that they're aware of the last forty years of language theory? ------------ One final idea I didn't manage to fit in above: duck typing relies on conventions. To exploit the language to the full you need to know these. Now they're documented in API docs, of course, but I get the feeling that there should be something more. To program well with duck types you need, more than in other languages, to "get" the "culture" of the language. I feel like Go should have added something here, but I don't know what (it has quite a rich set of tools for an independent language). Maybe I'm talking rubbish. It's just something I wanted to get out there.... And here's a thread that gives some pointers to earlier work that might have informed Go (see comments) - http://research.swtch.com/2009/12/go-data-structures-interfaces.html Andrew