Misc

Here's a miscellany of other Gosu features you might find useful:

Object Initializers

You can set properties of an object after it's constructor by using the object initializer syntax:

        
  var newObj = new MyClass() {
    :Prop1 = "Foo",
    :Prop2 = "Bar"
  }
      
This will construct the MyClass object and then set the Prop1 and Prop2 properties to the given values. This syntax is often useful when declaring "declarative"-like data, such as test or configuration data.

Classpath Statement + Shebang

Gosu programs can embed a classpath in their source, obviating the need for users to pass in a correct classpath externally:

        
  #! /path/to/gosu
  classpath "../src,../lib/sweet_lib1.jar"
  
  print( "Here is a sweet library object: ${new SweetLibraryObject()}")
      
The classpath statement is comma delimited, to avoid system specific dependencies. Each path on it will be added to the classpath. If a path points at a folder and that folder contains jars, all those jars will be added to the classpath as well.

This makes it much more pleasant to run gosu programs on *nix:

  Thumper carson$ ./my_sweet_gosu_program.gsp
    Here is a sweet library object: super.SweetLibraryObject@12b27c3
      
No wrapping scripts, no complicated class paths.

Using Statement

Rather than writing code like this:

          
  var conn = getConnection()
  try {
    conn.execute( "Some advanced SQL" )
  } finally {
      conn.close() 
  }
        
You can use the using statement:
          
  using( var conn = getConnection() ) {
    conn.execute( "Some advanced SQL" )
  }
        
The using statement will automatically clean up the resource for you.

Named Arguments

Gosu supports named arguments if two conditions are met:

Here's an example:
          
  function printIt( msg:String, escapeIt:boolean, printDate:boolean) {
    if( escapeIt ) {
      msg = msg.replace( "<", "&lt;" )
    }
    if( printDate ) {
      msg = (new Date()) + " " + msg
    }
    print( msg )
  }
  
  printIt( "<b>Hello World</b>", true, true ) // what does that mean?

  printIt( :msg = "<b>Hello World</b>", 
           :escapeIt = true, 
           :printDate = true )                // Oh.
        
When methods take lots of arguments, or lots of non-descript arguments like booleans, named arguments can help clarify your code dramatically.

Named arguments can also be combined with default parameters, discussed next, to make for great APIs.

Default Parameters

Gosu supports default parameter values. The printIt method could be rewritten like so:

        
  function printIt( msg:String, escapeIt:boolean = true, printDate:boolean = true) {
    if( escapeIt ) {
      msg = msg.replace( "<", "&lt;" )
    }
    if( printDate ) {
      msg = (new Date()) + " " + msg
    }
    print( msg )
  }

  printIt( "<b>Hello World</b>" ) // I'm happy with the defaults...
        
API designers take note: no need for telescoping methods in Gosu!

Feature Literals

Sometimes you want to refer to a method on a Class. Gosu lets you do that like this:

        
  var mr = String#substring(int)
      
You can then invoke the Method Reference like so:
        
  print( mr.invoke( "A String", 2 ) ) // the same as "A String".substring( 2 )
      
You can also bind a Method Reference to an instance:
        
  var mr = "A String"#substring(int)
  print( mr.invoke( 2 ) ) // same as above
      
As well as to parameters: You can also bind a Method Reference to an instance:
        
  var mr = "A String"#substring(2)
  print( mr.invoke() ) // same as above
      
Given a Method Reference, you can convert it to a block like so:
        
  var blk = mr.toBlock()
      
And you can get to the MethodInfo (The Gosu Type System equivalent of java.lang.reflect.Method) like so:
        
  var blk = mr.MethodInfo
      

There are equivalent references for Properties and Constructors

Finally, you can refer to feature chains:

  var methodChain = String#substring(int)#toUpperCase()
      
Feature chains are probably most useful when combined with properties, for things like UI-binding layers:
        
  var binding = aContact#Address#ZipCode
  var widget = new Widget(binding)
      
This (hypothetical) UI framework would then use the binding to get and set the value of the ZipCode field associated with the instance aContact.Address.

Range Operator

Gosu supports a range operator:

          
  var zeroToTenInclusive = 0..10
  var zeroToTenExclusiveOfTen = 0..|10
  var zeroToTenExclusiveOfZeroAndTen = 0|..|10
  for( i in zeroToTenInclusive ) {
    print( "i is ${i}" )
  }
        
The range operator works with numeric types and dates, as well as anything implementing gw.lang.reflect.interval.ISequenceable

Annotations

Gosu supports usage of Java annotations:

          
  @java.lang.Deprecated
  function oldCrustyMethod() : String {
    return "bah"
  }
        

Gosu also supports its own version of annotation declarations: implement gw.lang.IAnnotation and you are an annotation.

Annotations declared like this can be used the same way as Java-style annotations.

Call Site Validators

If you have an Gosu-style annotation that implements gw.lang.reflect.IMethodCallValidator, you can put that annotation on a feature and the annotation will be invoked at compile time. This allows you to plug in to the compiler and give additional feedback or put additional constraints on how a method is used.

For example, you might want to insist that your method only takes literals.

This API is very much in flux, but also pretty awesome.

Interface + Enhancement = Mixin

This is a "feature" noticed by Alan Keefer: if you create an Interface and then create an Enhancement on that interface, you've effectively created a Mixin: anyone who implements that interface gets all the enhancement functionality mixed in.