Why Gosu?Posted: November 11, 2010
There are kind of two sides to the answer. The first is the Guidewire-specific, historical part of the story: we needed a language with particular characteristics to use for configuring our applications (statically typed, dynamically compilable, some metaprogramming capabilities, fairly simple syntax and easy learning-curve for people familiar with Java or other similar imperative languages), and at the time that we started working on Gosu (back in 2002) there wasn’t really anything close to what we needed. We ended up creating it almost accidentally out of necessity.
But of course, that reasoning applies only to us, at Guidewire, and why we need something that we couldn’t find off-the-shelf. Why should you, if you’re someone outside Guidewire, care about Gosu?
As we worked on Gosu, we started to realize that we could actually turn it into a language that we, the language authors, liked, and that there’s currently a vacuum in the programming language landscape for the sort of thing that we were creating: a fairly “simple” (I realize that’s a massively loaded term, but bear with me) language that’s statically typed, dynamically compilable, with some metaprogramming capabilities, syntactic sugar in the most needed places, and with language features like closures, type inference, and enhancements that address some of the most glaring deficiencies and pain points in Java. We want to build something that, at least eventually, is unequivocally better than Java: a language that retains all the strengths of Java but has strictly fewer weaknesses.
Why target Java as the baseline? Because Java is, these days, essentially the lowest common denominator language for a lot of people, especially within the business community. It’s also the first language a lot of people learn in school these days. I have plenty of issues with Java myself, but it does a lot of things right as well, in my opinion: it’s statically typed, that static typing enables a huge array of tools for working with the Java language (i.e. excellent IDEs with refactoring support and error highlight as-you go), it can perform basically as fast as C or C++ for long-enough-running processes, it has garbage collection and a reasonable object-passing model (as compared to, say, worrying about pass-by-reference versus pass-by-value semantics) and a reasonable scoping model, the syntax is familiar enough to most other imperative languages that it’s not too much of a shock to transition from C or C++ or similar, and the lack of “powerful” language features also means that most people’s Java code looks pretty similar, so once you learn to read Java and understand the idioms you’re rarely thrown for a loop (with the glaring exception of generics).
Basically, Java manages to be a lowest common denominator language at this point that, while it’s lack of language features is really annoying, largely manages to avoid any absolute deal-breakers like poor performance, a lack of tools, or an inability to find (or train) people to program in it.
Now, that’s all speculation/opinion on my part as to why Java is where it is currently. You, the reader, are free to disagree with it. If you do agree in large part with that, though, it becomes clear what the imperative is for the next lowest-common-denominator language: it can’t screw up any of the things that Java got right, but it needs to improve on all the places where Java is weak.
So what are the deal-breakers to be avoided? The first is dynamic typing, in my opinion. Saying that is essentially flame-bait, I know, so I’m not trying to say that static typing is strictly better than dynamic typing, but merely that static typing enables certain things that people actually like about Java. Static typing enables all kinds of static verification, of course, which a lot of people find useful, especially on larger projects. When moving people between projects and forcing them to get up to speed on a new code base, for example, static typing can help make it obvious if you’re using a library even remotely correctly, or if your changes are going to clearly break someone else’s code. More important at this point, I think, is that static analysis enables amazing tooling: automatic error-detection as you type, auto-completion that actually lets you usefully understand and explore the code you’re working with (instead of, say, suggesting all functions anywhere with that name), automated refactoring, the ability to quickly navigate through the code base (for example by quickly going to the right definition of the “getName()” function you’re looking at, rather than one of the other 50 functions with that name somewhere in your code base).
Static typing also tends to be an important factor in execution speed, though dynamic languages are catching up there; you might argue that execution speed doesn’t matter anymore, but I’d argue that there’s always the possibility that it might matter in the future even if it doesn’t matter now, so at least in the business world people doing core systems work are often scared away by anything that they think has a performance disadvantage that might, at some point in the future, require them to purchase a bunch more hardware. You might disagree and attribute it to a failure of imagination on my part, but I find it hard to imagine the next LCD language being dynamically typed.
The second deal-breaker is what I’ll call “unfamiliarity.” There are lots and lots of people out there who know Java, or C, or C++, or C#, or even VisualBasic, and they’re so used to the standard imperative language syntax of those languages that something too foreign to that simply isn’t going to fly. It doesn’t matter how good the language is, or how expressive it is, something that doesn’t fit roughly into that mold simply won’t become the next LCD language, at least not any time soon.
The last deal-breaker is what I’ll call “complexity,” another obvious flame-bait term. Everyone’s got a different definition of the term, but here I’m equating it to roughly two related things: first of all, how hard is to fully learn and understand all features of a language, and secondly, for any two programmers A and B how different is their code likely to look/how easy is it for them to write code that the other one doesn’t understand. Again, I’m not trying to start a flame war, and opinions seems to very greatly on the relative complexity of languages, so hopefully we can all at least agree that if a language includes monads, a concept which historically many people have struggled to understand, that ups the complexity bar a fair bit, while a language like Ruby that doesn’t have them is probably a bit “simpler.” Likewise, languages like C and C++ with explicit pointers and memory management are more complex than languages that abstract out those details. Languages like Python where there’s one standard way to do things are also less “complex” by this metric than languages like Perl, where there are multiple ways to do everything, not so much because the individual features of Perl are complex but simply because it’s generally easier for Python Programmer A to read Python Programmer B’s code than it is for Perl Programmer A to read Perl Programmer B’s code. (Again, that doesn’t mean you can’t write readable, awesome code in Perl, I’m just talking about the presumed statistical average difference between two people’s coding styles.)
So to sum that all up: my theory (and I think I speak for the other Gosu designers as well) is that the next LCD language will be statically typed, imperative with a familiar syntax, and will avoid shall we say, “more advanced” language features.
So what can we add to Java to make it better? Well to start with we can add simple type inference with simple rules to make the language less verbose and make static typing impose less of a tax on your code. We can add in simple closures to make data structure manipulation or basic FP coding possible. We can add in enhancement methods so that people can improve APIs that they have to use without resorting to un-discoverable, ugly static util classes. We can add in first-class properties to avoid all the ugly get/set calls. We can add in syntactic sugar around things like creating lists and maps. We can add in dynamic compilation and first-class programs so that the language can scale down to be suitable for scripting. We can simplify the Java generics model and undo the travesty of wildcards. We can kill off the more-or-less failed concept of checked exceptions. And we can add in some metaprogramming capabilities, ideally in a way that’s relatively transparent to the clients of said capabilities so it doesn’t bump up the complexity factor too much.
If we do that, what we’re left with is a language that’s pretty good for most things, without too many (in my opinion, of course) glaring weaknesses: something fast, that allows for good tools, that scales down to small projects or up to big ones, that has enough expressiveness that you only have to write a little code to solve a little problem, that’s easy for programmers familiar with the existing LCD language to pick up, and that has enough metaprogramming capabilities to let you build good frameworks (because good frameworks, in my opinion, require metaprogramming . . . but that’s a different argument).
So merely in that sense, we think that Gosu fills a vacuum for a statically-typed JVM language that has a familiar syntax, doesn’t add too much complexity to Java, and which improves on Java in the most critical ways.
The last topic, which I haven’t really touched on at all, is around the metaprogramming allowed by Gosu’s type system. That’s worth another blog post simply in itself; the short version is that since the type system in Gosu is pluggable, that types can be generated or modified “on the fly” (i.e. really up front at parse time) to let you do things like take a WSDL and turn it into usable types that can be invoked just like any normal Gosu or Java class, but without having to do code generation. It’s the sort of thing that dynamic languages are incredibly good at but which, in a statically-typed language, has historically required reams of ugly code generation. There are other neat framework tricks you can do given that more runtime type information is available in Gosu than in Java or most other statically-typed languages. That’s what we really think will emerge, over time, as the killer feature of Gosu. For now, though, that’s less apparent, because it will only become a killer feature if people leverage it to create frameworks that other people want to use; it’s not the sort of thing you yourself will want to use every day, it’s something that you want other people to use when building the libraries and frameworks that you use every day.
So there you have it. That’s my (overly-verbose, as usual) explanation for why we think Gosu has a place in a world that already has so many existing language options; you most certainly don’t have to agree with my reasoning or my arguments, but hopefully it’s at least now clear what they are and what we’re trying to do. We’re not trying to push the language envelope in new directions, or to come out with language features no one’s ever thought of before; we’re trying to pick from the best ideas already out there, wrap them up in a pragmatic language that we’ve tried to keep simple and easy to pick up, and create something that will be appealing and useful to the very large number of programmers in this world who just want something relatively familiar that makes their programs easier to write and maintain without having to give up too many of the things that they’re already used to and have come to rely on.