Enhancements In GScript

You may wonder how we get all those great closure-based methods like findAll() and sortBy() onto classes (or interfaces!) in GScript. The secret is a language construct called Enhancements. Here is a stripped down version that puts the findAll() method onto java.util.List:

  uses java.util.*

  enhancement MySampleEnhancement : List {

    function findAll( filter(T):Boolean ) : List {
      var returnList = new ArrayList()
      for( element in this ) {
        if( filter( element ) ) {
          returnList.add( element )
        }
      }
    }

  }

So what does all that say?

Well, we define an enhancement named MySampleEnhancement, which enhances the List interface and adds one method: findAll(). findAll() takes a closure which takes a single parameter that is the same type as the list and returns true or false. If the closure returns true, the element is included in the (strongly typed) return list.

We could now use this method like so:

  var lst = new ArrayList(){"a", "ab", "abc"}
  var results = lst.findAll( \ s -> s.length >= 2 )

And the results would be ["ab", "abc"] since those strings have a length greater than or equal to two.

Note the ArrayList got this enhancement method because it implements the List interface.

Enhancements let you put new functionality where it belongs: on the object the functionality affects, rather than in static methods on a Utility class or in a helper object. It also makes the functionality more discoverable since programmers will see it when they are coding in Studio. Finally, using enhancements lets you fully leverage the GScript languages features even in types that are defined elsewhere.

Pretty neat, eh?


GScript > Java (pt. 3)

Here is how you sum up an array of integers in java:

  int[] values = ...
  int sum = 0;
  for( value : values ) {
    sum += value;
  }

Here is how you do it in gscript:

  var values = ...
  int sum = values.sum()

As a bonus, here is how you find the min, max and average:

  var min = values.min()
  var max = values.max()
  var average = values.average()

Not bad, eh?