GScript > Java (pt. 4)

A few weeks ago when I was writing some java code in the GScript runtime, I came across a situation where I needed to get all the ParseWarnings on a parsed element with a given resource tag, which is the unique identifier for the type of error. Turns out I had already written the code to get all the ParseErrors that had a given resource code. It looked like this:

  public List<ParseError> getParseErrorsOfType(  ResourceKey key ) {
    ArrayList<ParseError> lst = new ArrayList<ParseError>();
    for( ParseError pe : getParseErrors() ) {
      if( pe.getResouceKey() == key ) {
        lst.add( pe );
    return lst;

Now, I could have just duplicated that method and replaced Error with Warning and everything would have been fine. But that’s a bit offensive because getResourceKey() is a method on ParseIssue, which is the base class of ParseError and ParseWarning, and it just seems wrong to duplicate that much code. So I stared at it a bit and then realized (with Keefs help) that I was going to have to put my generics hat on and write a generic method:

  public <T extends ParseIssue> 
         List<T> getParseIssuesOfType(  ResourceKey key, List<T> src ) {
    ArrayList<T> lst = new ArrayList<T>();
    for( T pi : src ) {
      if( pi.getResouceKey() == key ) {
        lst.add( pi );
    return lst;

And I could then write these methods:

  public List<ParseError> getParseErrorsOfType(  ResourceKey key ) {
    return getParseIssuesOfType( key, getParseErrors() );

  public List<ParseWarning> getParseWarningsOfType(  ResourceKey key ) {
    return getParseIssuesOfType( key, getParseWarnings() );

Well, going through all that had a certain intellectual frisson, I’ll admit, as I pieced together exactly what arguments I had to pass in and how to declare the generic method correctly. Loads of fun. But it took me about two minutes to get it all just right. Now, I don’t consider myself the sharpest tool in the shed but I’m not a total idiot and I think I’ve got a better than average handle on generics. Despite this, I had to stop for a couple of minutes, put on my aforementioned generics hat, bust out my slide-rule and write that incomprehensible code. In pure clock time it would have been a lot faster to just duplicate the method, feel bad about it for a second, and then move on.

Soooooo, let’s look how I would have implemented that method if I were lucky enough to be writing it in GScript:

  function getParseErrorsOfType(  key : ResourceKey ) : List<ParseError> {
    return ParseErrors.findAll( \ pe -> pe.ResourceKey == key )

Now, that’s a method that I feel a lot less bad about duplicating. Good old ctrl-d and a quick edit gives:

  function getParseWarningsOfType(  key : ResourceKey ) : List<ParseWarning> {
    return ParseWarnings.findAll( \ pw -> pw.ResourceKey == key )

That would take me about ten seconds and I’d move on with nary a thought, and the amount of code duplication is nearly as negligible as the java solution above.

And that’s something profound.

The type-inference and closures that GScript offers allow you to pack a lot more meaning into a single line, helping you avoid writing helper methods and classes, all of which bog your code down with unnecessary weight. The type-inference, in particular, dramatically reduces the burdens of generics, allowing you to skate along the surface of your algorithms without delving too deeply into the type details. Things just work themselves out.

So, in short, GScript makes the easy solution also the right solution.


One Comment on “GScript > Java (pt. 4)”

  1. […] a side note, as I’ve said elsewhere, any non-trivial application of generics requires me to stop and put on my generics hat, and, ten […]

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s