home mail me! RSS (2.0) feed

Groovy: Java++ by being Java–

What? Yet another dynamic scripting language for the JVM? Are you not fed up with the Java-based, and rarely used, implementations of the hyped languages Ruby and Python?

Sit down and let me explain.

Groovy is actually not a brand new language, but rather an extension of Java. The difference between this extension and that of, say C++ over C is that Groovy extends Java by simplifying constructs, ridding the developer of much of the repetitive rituals associated with Java development. So it is fair to say that

Groovy is Java++ by being Java--

This post will only touch at the power of Groovy by slowly going from Java to a fully Groovish script, so if you lack something cool in these descriptions, do not despair.

Installing Groovy and Grails

Groovy is easiest installed by expanding the ZIP file of the latest release on the Groovy download page - I use version 1.5.6 - and placing it somewhere, just remembering to set an environment variable GROOVY_HOME to point to that location and PATH to include the bin directory of that location. If you do not know how to do this, I am sorry, this blog is not for you. See you later!

Groovy = Java++

First of all, Groovy is (almost...) a super set of Java, so the following snippet is a valid Groovy script:

JAVA:
  1. import java.util.*;
  2.  
  3. class TestList {
  4.     public static void main(String[] args) {
  5.         List higherSpirits = Arrays.asList("Luke", "Daniel", "David", "Jesus");
  6.         Iterator iter = higherSpirits.iterator();
  7.         int totalLength = 0;
  8.         while (iter.hasNext()) {
  9.             String name = (String)iter.next();
  10.             totalLength += name.length();
  11.         }
  12.         System.out.println("The total length of the names of the higher spirits is " +
  13.                 totalLength);
  14.     }
  15. }

If you recognize the syntax, you are right, this snippet is also a Java application. So, we are done, you, as a presumed Java developer, already know how to write a Groovy app ;)

NOTE: I am aware that it is not the optimal solution in Java 5, but it is quite typical for most Java developers.

Let us verify that it indeed is a valid Groovy application. We here encounter the first difference between how Java and Groovy handle applications: whereas we need to compile the Java application separately from the execution phase, both can be combined in Groovy. No, this does not make Groovy interpreted, just compilable-on-demand (not to confuse with JIT, which is a further step of compilation from bytecode to a native format.

So, let us do try with an explicit compilation phase first:

groovyc TestList.groovy
java TestList

We see that we get a regular bytecode file, TestFile.class, as a result of the compilation, so we can just run the class as any old Java-genereted class having a static main, right? Well, not really, we get the only aesthetic output of a JVM: a stack trace telling us that a lot of classes are not defined.

The Groovy compiler does inject some fanciness into the bytecode so it can be used from other Groovy code with the extra bells and whistles. Luckily, the fanciness consists of use of one specific bytecode library: $GROOVY_HOME/embedded/groovy-all-VERSION.jar.

So, let us add that Groovy library to the classpath:

java -cp .:$GROOVY_HOME/embedded/groovy-all-1.5.6.jar TestList

We get the output:

The total length of the names of the higher spirits is 20

I promised we could do both steps - compilation and execution - in one step. Here it is:

groovy TestList.groovy

The same output, but no visible class file anywhere. REPEATING: (since even quite senior developers confuse matters here: AlBlu's weblow) this does not mean the language nor implementation is interpretative. And, no, dynamic is not synonymous for interpreted.

Let us look at how Groovy allows us to reduce the verbosity of this code.

Groovy = Java--

Putting Script Outside Class

Is it not irritating how we need to put the code to be executed upon entry in a special method inside a class construct? What if we could just skip all that silly nonsense, and just put the main code as is in the file?

With Groovy, we can:

JAVA:
  1. import java.util.*;
  2.  
  3. List higherSpirits = Arrays.asList("Luke", "Daniel", "David", "Jesus");
  4. Iterator iter = higherSpirits.iterator();
  5. int totalLength = 0;
  6. while (iter.hasNext()) {
  7.     String name = (String)iter.next();
  8.     totalLength += name.length();
  9. }
  10. System.out.println("The total length of the names of the higher spirits is " +
  11.         totalLength);

This creates the class and main method behind the scenes.

Literal lists

Can we do even better? In my world, reducing redundant syntax is good.

Groovy has literal lists (of type ArrayList):

JAVA:
  1. import java.util.*;
  2.  
  3. List higherSpirits = ["Luke", "Daniel", "David", "Jesus"];
  4. Iterator iter = higherSpirits.iterator();
  5. int totalLength = 0;
  6. while (iter.hasNext()) {
  7.     String name = (String)iter.next();
  8.     totalLength += name.length();
  9. }
  10. System.out.println("The total length of the names of the higher spirits is " +
  11.         totalLength);

No need for semi-colons

Why type all those semi-colons, even though we know that the compiler knows (in most cases) when one statement ends and the other begins anyway; this is why you get the pesky error messages of missing ';', because the compiler knows.

Groovy lets the compiler do its thing here:

JAVA:
  1. import java.util.*
  2.  
  3. List higherSpirits = ["Luke", "Daniel", "David", "Jesus"]
  4. Iterator iter = higherSpirits.iterator()
  5. int totalLength = 0
  6. while (iter.hasNext()) {
  7.     String name = (String)iter.next()
  8.     totalLength += name.length()
  9. }
  10. System.out.println("The total length of the names of the higher spirits is " +
  11.         totalLength)

That was a relief.

Anything else we can do?

Closures and list visitors

This word has definitely become a buzzword lately: closures. Some of us have used them for three decades, but what the heck, let's ride that buzz!

Groovy allows for functions to be passed around as any other value, i.e., they are first-class citizens, opening up for all kinds of higher-order magic. Furthermore, these functions can refer variables declared outside the body, or parameter list, of the function, i.e., they are closures.

So, we can pass closures around, but how can we create them? It turns out that there are exactly two ways to create a closure in Groovy, without using the underlying Closure class and resorting to old school Java constructs:

  1. using a closure literal
  2. converting a pair of an object and a method

But what use is a closure without a higher-order function to apply it (subsequently)? It turns out that Groovy has a lot of visitor-kind of higher-order functions for sequences, such as lists. One such function is each, which applies a given closure to all the elements:

JAVA:
  1. import java.util.*
  2.  
  3. List higherSpirits = ["Luke", "Daniel", "David", "Jesus"]
  4. int totalLength = 0
  5. higherSpirits.each { name ->
  6.     totalLength += name.length()
  7. }
  8. System.out.println("The total length of the names of the higher spirits is " +
  9.         totalLength)

We also see a syntactic convenience in that you can skip the parentheses when passing a closure. Groovy closure literals look like { param -> body }, and one can in fact skip the param -> when using one parameter and use the lexeme it for the use of the only parameter in the body.

Automatically imported packages and the 'it' parameter

Groovy has many more packages imported by default than Java; well, it is not hard to beat one ;) Let us use that fact:

JAVA:
  1. List higherSpirits = ["Luke", "Daniel", "David", "Jesus"]
  2. int totalLength = 0
  3. higherSpirits.each { totalLength += it.length() }
  4. System.out.println("The total length of the names of the higher spirits is " +
  5.         totalLength)

Uniform size methods, GStrings and a simple print method

Do you impress interviewers by your knowledge of the idiosyncratic variants of getting the size of various containers? In Groovy you can avoid showing that impressive feat, they all have a size() method. Furthemore, Groovy has this thing called GString which allows for variables inside a string literal. We use such a GString inside Groovy's simple print method:

JAVA:
  1. List higherSpirits = ["Luke", "Daniel", "David", "Jesus"]
  2. int totalLength = 0
  3. higherSpirits.each { totalLength += it.size() }
  4. println "The total length of the names of the higher spirits is ${totalLength}"

But where are all the dynamic types? After all, Groovy is a dynamic language, right?

Yes and no. It allows for agnosticism w.r.t. the types of values and variables, but one can, as you have seen, use static types. In fact, so far there is only one place in the code with a dynamic type. Guess where.

Yes, you got it: the it parameter is dynamically typed.

Dynamic types

A dynamically typed variable is introduced with def variableName. I will not discuss the merits of using static or dynamic types here, but just let you know that with Groovy, just like with Objective-C, you have a choice.

Let us see the more dynamically typed code:

JAVA:
  1. def higherSpirits = ["Luke", "Daniel", "David", "Jesus"]
  2. def totalLength = 0
  3. higherSpirits.each { totalLength += it.size() }
  4. println "The total length of the names of the higher spirits is ${totalLength}"

Higher-order functions

We have already seen one higher-order function, the method each of lists, which is just the good old Visitor Pattern.

But in this particular example, there is something much more interesting we can do. We are summing something and there happens to be a sum method of lists. But we are not summing up (i.e., concatenating) the string, but the sizes. So we need to transform the list of strings to a list of sizes first, which can be done by the collect function. Combining the two:

JAVA:
  1. def higherSpirits = ["Luke", "Daniel", "David", "Jesus"]
  2. def totalLength = higherSpirits.collect { it.size() }.sum()
  3. println "The total length of the names of the higher spirits is ${totalLength}"

Collect and apply in one

Groovy has a special syntax for dealing with applying a method to all elements of a list, with a "*.". We use that and skip the intermediate variable higherSpirits:

JAVA:
  1. def totalLength = ["Luke", "Daniel", "David", "Jesus"]*.size().sum()
  2. println "The total length of the names of the higher spirits is ${totalLength}"

Please compare this to the original Java-ish snippet, and you will wonder why you stick with Java at all.

To be fair, there are downsides of using Groovy, such as all indirections they use to get the dynamics. I will take that up, in detail, in later blog posts.

If you need to learn more about Groovy now, buy one of the following two books (there are some more, but these are by far the best ones):

Groovy in Action
Programming Groovy: Dynamic Productivity for the Java Developer (Pragmatic Programmers)

mhyst said,

May 9, 2008 @ 10:13 am

Hi,

That’s very interesting and well explained. I guess that Groovy simply turns that code into real Java, doing a lot of work for us (of course). But then… it just makes a call to “javac”?

If that’s the case, the sentence “compilation on demand” means that: groovy compiles it if it hasn’t already compiled before?.

Closures are really interesting. I got a lot of new ideas for my ongoing programming language (Lilisp). Lol

Thank you again!

PS: It’s nice to read you again.:)

Development in a Blink » Blog Archive » Java and Groovy can do it. Why not C# and PowerShell. said,

May 13, 2008 @ 8:30 pm

[…] David Bergman presented Groovy: Java++ by being Java– at Lab49 which inspired me to record this 7min Video doing the same with C# and PowerShell. […]

Daily del.icio.us for May 12th through May 16th — Vinny Carpenter’s blog said,

May 16, 2008 @ 9:00 am

[…] davber does IT » Groovy: Java++ by being Java– - Groovy is actually not a brand new language, but rather an extension of Java. The difference between this extension and that of, say C++ over C is that Groovy extends Java by simplifying constructs, ridding the developer of much of the repetitive rituals […]

RSS feed for comments on this post · TrackBack URI

Leave a Comment

You must be logged in to post a comment.