Open Source

Language of the Month: Gosu

A statically typed language with user-defined types? Functions that can be defined anywhere in the class path and applied to all downstream objects? Indeed! Gosu delivers unusual and powerful features

The development of Gosu began about nine years ago during the earliest stage of engineering at Guidewire Software. The language's humble origin sprang from an unsuccessful search for a scripting language as the basis for a rule engine we needed to build. Our language criteria didn't seem too demanding; but we were naive. First and foremost, the language had to be embeddable in the JVM and be compatible with leading application servers. It also had to be familiar  the vast majority of programmers are comfortable with imperative, object-oriented languages, and we wanted our scripting language to be the same. We also wanted a language with static typing, so that our customers could edit rules with instant parser feedback and we could provide modern features, such as deterministic code completion, navigation, etc. In addition, we needed to represent our ORM as a set of first-class types in the language, whether it be through code generation or meta-programming or what have you. Lastly, the entity types from our ORM needed to be individually configurable by our customers via custom methods and properties. To our dismay, all the serious scripting languages at that time were dynamically typed, which ruled them out. So began the development of Gosu (which is today an open-source language, available at http://gosu-lang.org).

By the time we had a working language, we started seeing it as a solution for rewriting our company's product UIs, our document management system, our Velocity-template systems; and each step exposed new features that were needed in the language. Of these, by far the most innovative aspect of Gosu is the open type system. Unlike other languages, Gosu's type system is statically extendable to external domains, whereby abstract types can be defined and exposed with first-class representation. This is a big deal and is what makes Gosu extremely vital to the success of our enterprise applications.

Although the type system is what separates Gosu from other JVM languages, we made sure that as a language, Gosu did not suffer from the limitations of so many others. As Java developers, we were and remain to this day feature-starved relative to other languages. Microsoft's C#, for instance, had led the way with productivity boosting features, while Java stagnated or missed the mark. Thus, we borrowed heavily from C# and other languages. Along the way, Gosu picked up properties, type inference, reified (and simplified) generics, composition, closures, eval support, RAII, null-safety, and a host of other useful features. And as you'll soon see, Gosu's syntax is familiar to anyone with Java or C# experience.

One last bit of history involves Gosu's performance. Although Java as a language is showing its age, we can't knock it on performance  it's blazing fast and is still the leader of the pack. Other languages are gaining, but because most are dynamic (e.g., Groovy, JRuby, Jython), they have inherent limits with respect to performance and will never quite approach Java's. For instance, the bytecode they generate for a method call is unconventional and involves a lot of hoop jumping and sophisticated caching techniques. Although a lot of work has gone into the compilers of various dynamic languages, they'll never quite attain the performance of a virtual method call. Gosu was originally a semi-interpreted runtime, but it evolved to be fully bytecode compiled. And because it is statically typed, its compiler generates conventional bytecode, which keeps fair pace with Java. We have more work to do to make areas unique to the language perform even better, but we're comfortable with its performance on the whole.

Features

VariablesFrom the start, we wanted programmers to feel comfortable with Gosu at first sight. That is, we didn't want to reinvent the wheel or model the language after peripheral or academically motivated languages. Initially, since we were only interested in building a scripting language, we modeled Gosu after the most popular scripting language in use, JavaScript. The syntax is easily understood by most programmers and we could make it statically typed with a few simple changes to its grammar. For instance, local variables are declared with the var keyword and don't require a type declaration if initialized (i.e., the type can be inferred). For example, the following declarations are logically identical:

var name = "fred"
var name : String = "fred"

Java programmers new to Gosu quickly learn to ditch the unnecessary type declarations in favor of type inference. If this is not obvious, consider an example involving generics:

var map : HashMap<String, Company> = new HashMap<String, Company>()

versus:

var map = new HashMap<String, Company>()

Which would you rather read/write?

You've probably noticed the Pascal-style declaration syntax  the type follows the name. Coming from a C-derived language like Java, it may seem awkward at first; but it makes sense coming at it from first principles. Most often, we don't need to see the type; and when present, it is of lesser significance than the name. It feels natural after a bit of exposure.

You may have also noticed the absence of semi-colons as statement terminators. They're optional in Gosu and rarely used.

ClassesWhen Gosu transitioned from a scripting language to a general-purpose language, it gained types in the form of classes, interfaces, enums, and enhancements. As the next generation of JavaScript (EcmaScript 4) was nearly identical to Java with respect to type declaration syntax, we followed suit. The following example defines a simple class:

As you can see, there are a lot of similarities both structurally and syntactically between Gosu and Java. Just like Java, a statement is required to declare the class's package. Also, uses-statements are required to enable relative type name references used later in the class. The class header syntax is identical to Java's with the exception of access modifiers; Gosu assumes public access in the absence of a modifier. Fields are declared identically to local variables, the default access is private. The construct keyword is used instead of using the class's name. Similarly, the function and property keywords are used to indicate function and property declarations, and both have public default access.

Properties can be defined with shorthand as-clause syntax if they simply reflect the value of a field:

var _make : Make as Make

This syntax is logically equivalent to the explicit declaration of the get/set property methods, which saves a bunch of typing (and reading). Note the capitalization of property names; this is a convention in Gosu.

The source for a class is stored as a file with a .gs extension. And like Java, the source file must reside in a directory structure that reflects the class's package name with respect to the class path.

Programs and ExpressionsOne convenient byproduct of designing our language from the start as an embeddable scripting language is that we not only have proper types, but we also have free-style scripting in the form of Programs. A program source file has a .gsp extension and is directly executable. So, unlike Java, Gosu doesn't require a boilerplate class with a main() method in order to run some code. Instead, you simply write it and run it. Here's the obligatory Hello World example in Gosu:

print( "Hello World!" )

If need be, your program can access command line parameters dynamically or statically via the built-in CommandLineAccess type.

A program can contain any mix of statements, functions, properties, and classes. But a program doesn't have to exist as a file on disk or execute from the command line. As an embeddable language, Gosu provides services to parse, compile, and execute simple expressions, programs, and templates directly from memory.

TemplatesGosu templates are a lot like JSP templates, but they're built into the language and are represented as first-class types. Here's a quick example:

Templates have a .gst extension and follow the same naming rules as classes and programs. You execute templates by calling static methods on the type. For example, if the preceding template were named "foo.HelloWorld.gst," you could render the template to a String as follows:

var content = foo.HelloWorld.renderToString()

Note you can declare parameters in a template using the params directive. The methods on the template type reflect the parameters statically.

EnhancementsEver wanted to add methods to an existing type like String or List? That's exactly what enhancements provide. An enhancement looks a lot like a class:

Just by existing in the classpath, this enhancement adds the reverse() method to Java's String class. In Gosu, you can call it directly:

"Hello".reverse()

An enhancement file has a .gsx extension and follows the same naming rules as classes. An enhancement can contain any number of functions and properties and can also enhance types generically. Note that you never reference enhancements by name in your code. The type system discovers them and modifies type information automatically. Gosu ships with a boatload of core enhancements  mostly around collections, where we leverage closures.

ClosuresFunctions in Gosu can be first-class values  they can be created anonymously, passed to or returned from other functions,and assigned to variables just like any other type. They can also refer to other variables in the local scope. A value with these properties is called a closure (or lambda) expression or a block or an anonymous function. Call them what you will, they are extremely useful for performing operations on collections. Consider the following Java code:

Ignoring the amount of code to initialize the list (ugh!), filtering it in Java involves manually creating another list, and then iterating over the original one while populating the filtered one. How many times have you written this code? I'll wager too many times.
Now consider the equivalent code in Gosu using enhancements with closures:

The syntax is simple. The backslash character "\" signals a closure, followed by parameters, followed by the –> operator, and then an expression or statement. Typically, a closure is a simple expression. In this example, I utilize the where() method defined in an enhancement on Java's Iterable interface. The where() method is declared as follows:

Notice a closure parameter is declared just like a simple parameter with the addition of a parameter list following the name. This particular closure has a parameter with type T, which is a type variable on the enhancement (as it enhances the generic type Iterable). The important thing to understand is that this code is written once and only once. It's tucked away inside an enhancement, so you'll never have to write it (or read it). You only need to concern yourself with the criteria on which you filter your collections.

CompositionGosu provides direct support for composition as an alternative to inheritance by way of interface delegation.

Gosu automatically delegates the implementation of interfaces represented by delegates. It eliminates all the boilerplate code you would otherwise write in Java to do the delegation manually. This small feature enables more flexible architectures based more on composition.

More...There is not nearly enough space in this article to even touch on all of Gosu's features. In fact, I've barely scratched the surface. I didn't cover Gosu's type inference capabilities, which help reduce code while maintaining excellent readability. Also missing from this discussion are reified generics, RAII support, eval(), intializers, named arguments, intervals, dimensions, improved exception handling, and lots more. Please see the Gosu website for more information.

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task.
However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

Video

This month's Dr. Dobb's Journal

This month,
Dr. Dobb's Journal is devoted to mobile programming. We introduce you to Apple's new Swift programming language, discuss the perils of being the third-most-popular mobile platform, revisit SQLite on Android
, and much more!