The Lazy Gosuer
Less Code, More Beer

Intro

I don't have time to write a book.

You probably don't have time to read a book.

So, how about a quick introduction to Gosu and how to get productive in it, instead?

Gosu is an imperative, statically typed programming language for the JVM. It is designed to be a easy for Java developers to pick up. If falls between Groovy, which is an imperative, dynamically typed language (with optional type annotations) and Scala, which is a functional-ish, statically typed language.

It's nothing like Clojure, which is a Lisp variant and, therefore, insane.

Why?

Why learn Gosu, given all the alternatives out there? Here are three reasons:

Installing

And that's it. You can now run Gosu using the scripts in the bin directory of the gosu distribution.

Playing

Gosu ships with a small built in editor that you can use to play around with. If you run bin/gosu with no arguments, you should get a window like this:

You can use this to play around with gosu, write simple programs, etc. The editor offers simple code completion and a few other niceties:

Some useful keyboard shortcuts are:

Programs

Gosu doesn't have the concept of a public static void main(String[] args) method, because that's just crazy. Instead, it has programs, like Ruby or Python, which are bits of Gosu code in a file ending in the .gsp extension.

Here is hello_word.gsp:

          
  print( "Hello World!")
        
Easy enough, right?

You run this program like so:

          
  Thumper carson$ gosu hello_world.gsp
  Hello World!
  Thumper carson$
        

You can use the gw.lang.cli.CommandLineAccess class to get at arguments passed to your Gosu program.

Setting Up A Project

My favored approach right now is to lay out a project like this:

  /proj_name
    /src - Gosu classes, XSD's, WSDL's, etc.
    /lib - 3rd party jars
    /bin - Gosu programs
    /test - A directory for your tests
    build.vark - An Aardvark build file.
        

Given this layout, you can add the following to the top of your gosu programs in the /bin directory:

          
  classpath "../src,../lib"
        
This classpath statement will add the src directory and all jars in the lib directory to the classpath when this program is launched, so you can run your project without any crazy command line setup or secondary scripts:
        
  Thumper carson$ gosu bin/my_prog.gsp
  Hello Gosu Projects!
      

The classpath statement is discussed more on the Misc page

Math

Gosu supports the usual math operators, and they work on the major primitive and non-primitive numeric types, such as BigDecimal and BigInteger

Comparisons

Gosu supports the usual comparison operators:

Logical Operators

Gosu supports the usual logical operators, and you can use either the english style not, and and or, or the C-style equivalents. I use the english style operators.

Variables and Control Flow

In Gosu, you typically do not need to declare the type of variables:

        
  var x = 10
  print( x + x ) // prints 20
      
Gosu will infer the type of x to be int.

If you want to explicitly type the variable, you put the type annotation after the variable name:

            
  var x : int = 10
  print( x + x ) // prints 20
          

If

The if statement works just like it does in every other sane language:

          
  var x = 10
  if( x > 5 ) {
    print( "x was greater than 5")
  }
        

For

The for statement is similar to other languages:

          
  var aList = {"a", "b", "c"} // declare a List<String>
  for( x in aList ) {
    print( x )
  }
       
The for statement works with both arrays and classes that implement java.lang.Iterable. Note that x is explicitly typed to java.lang.String above, via type inference.

Sometimes you want the index of an iteration. You can use this syntax to get it:

          
  var aList = {"a", "b", "c"}
  for( x in aList index i ) {
    print( i + ":" + x )
  }
        
i will be the zero-based index of the current loop of the iteration.

Sometimes you want the iterator for the loop. You can use this syntax to get it:

          
  var aList = {"a", "b", "c"}
  for( x in aList iterator it ) {
    it.remove()
  }
        
it can be used to safely remove items, for example.

Note that the for loop is null safe: no NPE occurs if aList is null, rather the loop simply does not execute.

Etc.

Gosu has while, do/while and switch statements, all of which work like you would expect.

Working With Types

Gosu allows you to determine the runtime type of a value with the typeof operator:

        
  var x = "This is a String"
  var t = typeof x
  print( t.Name ) // prints java.lang.String
      
It the code above, the type of t is gw.lang.reflect.IType, which is the Gosu Type System's equivalent of java.lang.Class

Gosu has a way to test if an object is an instance of a type, akin to Java's instanceof keyword: typeis. Here is an example:

        
  var x : Object
  x = "A String"
  if( x typeis String ) {
    print( "x is a String with length " + x.length )
  }
      
One interesting thing about the typeis operator is that how it interacts with logical operators and the if statement. In the code above, note that x was not cast to String, but within the if statement the length property on String was used. Gosu automatically downcast x to String after the typeis expression, so no casting was necessary.

Properties

Gosu supports properties, which are a bit like public fields in Java, but they allow you to associate logic with the reading and writing operations. We will cover property definition below, but this is how you access them:

          
  var p = new MyGosuPersonClass()
  p.Name = "Joe"
  print( "The name of this person is ${p.Name}")
        
Properties have some interesting and useful characteristics that will become apparent over time (e.g. they are both an rvalue and an lvalue.)

Gosu automatically converts get/set methods in Java classes into properties, so the following Java class:

          
  public class MyJavaPersonClass {
    String _name;
    
    public String getName() {
      return _name;
    }
    
    public void setName( String s ) {
      _name = s;
    }
  }
        
Can be used like so:
          
  var p = new MyJavaPersonClass()
  p.Name = "Joe"
  print( "The name of this person is ${p.Name}")
        

Null Safety

If you wish to make a null-safe call to a method or property, you can prefix the '.' operator with a question mark, '?':

          
  var x : String = null
  print( x?.length ) // prints "null"
        

Classes

Gosu classes are defined with much the same syntax as other programming languages. You can define classes inside a Gosu program, or in a file ending with the .gs extension. Here is a basic class:

          
  uses java.util.List

  class SampleClass {
    var _names : List<String> // a private class variable, which is a list of Strings

    // A public constructor
    construct( names : List<String> ) {
      _names = names
    }

    // A public function
    function printNames( prefix : String ) {
      for( n in _names ) {
        print( prefix + n )
      }
    }

    // A public property getter, making 'Names' a read-only property
    property get Names() : List<String> {
      return _names
    }
  }
        
The above code demonstrates the following features:

Shorthand Property Syntax

Exposing a field as a property is a common pattern, so there is a short hand syntax for it:

          
  class SampleClass {
    var _names : List<String> as Names

    // A public constructor
    construct( names : List<String> ) {
      _names = names
    }

    // A public function
    function printNames( prefix : String ) {
      for( n in _names ) {
        print( prefix + n )
      }
    }
  }
        
The 'as Names' bit exposes the _names field as both a readable and writeable a property. If you want the property to be read only, you can add the readonly modifier after the as keyword.

Named Arguments and Default Parameter Values

Gosu supports names arguments and default parameter values to help smooth out APIs. Let's say you wanted to make the argument to printNames() optional, with a default value of "> ". You could change the declaration to:

        
  // A public function
  function printNames( prefix : String = "> ") {
    for( n in _names ) {
      print( prefix + n )
    }
  }
        
And now invoke it like so:
          
  var c = new SampleClass({"joe", "john", "jack"})
  c.printNames() // No argument is necessary, it will use the default value of "> "
  
Additionally, Gosu allows you to use named arguments when you are working with non-overloaded methods on Gosu classes:
        
  var c = new SampleClass({"joe", "john", "jack"})
  c.printNames(:prefix = "* ")
  
This can be used to clarify code, so you don't end up with stuff like this:
  someMethod(true, false, null, false, true)  //bwah?
  
  someMethod( :enableLogging = true, :debug = false, 
              :contextObject = null, :trace = false, 
              :summarizeTiming = true)  //Oh, I see
      

Superclasses, Interfaces and Delegates

Gosu classes can extend other classes and implement interfaces, just like in Java, using the extends and implements keywords respectively.

One interesting additional feature of Gosu is the ability to delegate the implementation of an interface to a class variable:


  uses java.lang.Runnable

  class MyRunnable implements Runnable {
    //A delegate, exposed as the Impl property
    delegate _runnable represents Runnable
  
    property get Impl : Runnable {
      return _runnable
    }
  
    property set Impl( r : Runnable ) {
      _runnable = r
    }
  }
      
MyRunnable does not declare a run() method, like Runnable requires. That's because the delegate field _runnable is implementing the method for it:
        
  var x = new MyRunnable()
  x.Impl = new Runnable() {
    function run() {
      print("Hello, Delegation")
    }
  }
  x.run() // prints "Hello, Delegation"
      
Delegates give you a convenient way to favor composition over inheritance.