October 23, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Groovy Code Notation: Like Java, Only Different

  • May 21, 2010
  • By Dierk König, Guillaume Laforge, Paul King, Jon Skeet
  • Send Email »
  • More Articles »

Code as objects: closures

The concept of closures is not a new one, but it has usually been associated with functional languages, allowing one piece of code to execute an arbitrary piece of code that has been specified elsewhere.

In object-oriented languages, the method-object pattern has often been used to simulate the same kind of behavior by defining types whose sole purpose is to implement an appropriate single-method interface so that instances of those types can be passed as arguments to methods, which then invokes the method on the interface.

A good example is the java.io.File.list(FilenameFilter) method. The FilenameFilter interface specifies a single method, and its only purpose is to allow the list of files returned from the list method to be filtered while it's being generated.

Unfortunately, this approach leads to an unnecessary proliferation of types, and the code involved is often widely separated from the logical point of use. Java uses anonymous inner classes to address these issues, but the syntax is clunky and there are significant limitations in terms of access to local variables from the calling method. Groovy allows closures to be specified inline in a concise, clean, and powerful way, effectively promoting the method-object pattern to a first-class position in the language.

Because closures are a new concept to most Java programmers, it may take a little time to adjust. The good news is that the initial steps of using closures are so easy that you hardly notice what is so new about them. The aha-wow-cool effect comes later, when you discover their real power.

Informally, a closure can be recognized as a list of statements within curly braces, like any other code block. It optionally has a list of identifiers in order to name the parameters passed to it, with an -> arrow marking the end of the list.

It's easiest to understand closures through examples. Figure 4 shows a simple closure that is passed to the List.each method, called on a list [1, 2, 3].

An example list in Groovy
Figure 4.
A simple example of a closure that prints the numbers 1, 2, and 3

The List.each method takes a single parameter -- a closure. It then executes that closure for each of the elements in the list, passing in that element as the argument to the closure. In this example, the main body of the closure is a statement to print out whatever is passed to the closure, namely the parameter we've called entry.

Let's consider a slightly more complicated question: if n people are at a party and everyone clinks glasses with everybody else, how many clinks do you hear? (Or, in computer terms: what is the maximum number of distinct connections in a dense network of n components?) Figure 5 sketches this question for five people, where each line represents one clink.

An example list in Groovy
Figure 5.
Five elements and their distinct connections, modeling five people (the circles) at a party clinking glasses with each other (the lines). Here we have 10 clinks.

To answer this question, we can use Integer's upto method, which does something for every Integer starting at the current value and going up to a given end value. We apply this method to the problem by imagining people arriving at the party one by one. As people arrive, they clink glasses with everyone who is already present. This way, everyone clinks glasses with everyone else exactly once.

Listing 5 shows the code required to calculate the number of clinks. We keep a running total of the number of clinks. When each guest arrives, we add the number of people already present (guestNumber–1). Finally, we test the result using Gauss's formula for this problem -- with 100 people, there should be 4,950 clinks. (Johann Carl Friedrich Gauss (1777–1855) was a German mathematician. At the age of seven, his teacher wanted to keep the kids busy by making them sum up the numbers from 1 to 100. Gauss discovered this formula and finished the task correctly and surprisingly quickly. There are different reports on how the teacher reacted.)

Listing 5 Counting all the clinks at a party using a closure
def totalClinks = 0
def partyPeople = 100
1.upto(partyPeople) { guestNumber ->
    clinksWithGuest = guestNumber-1
    totalClinks += clinksWithGuest     // #1 modifies outer scope
}
assert totalClinks == (partyPeople * (partyPeople-1)) / 2


How does this code relate to Java? In Java, we would have used a loop like the following snippet. The class declaration and main method are omitted for the sake of brevity:

// Java snippet
int totalClinks = 0;
int partyPeople = 100;
for(int guestNumber = 1;
        guestNumber <= partyPeople;
        guestNumber++) {
    int clinksWithGuest = guestNumber-1;
    totalClinks += clinksWithGuest;
}


Note that guestNumber appears four times in the Java code but only twice in the Groovy version. Don't dismiss this as a minor thing. The code should explain the programmer's intention with the simplest possible means and expressing behavior with two words rather than four is an important simplification.

Also note that the upto method encapsulates and hides the logic of how to walk over a sequence of integers. That is, this logic appears only one time in the code (in the implementation of upto). Count the equivalent for loops in any Java project and you'll see the amount of structural duplication inherent in Java.

The example has another subtle twist. The closure updates the totalClinks variable, which is defined in the outer scope. It can do so because it has access to the enclosing scope. That it pretty tricky to do in Java. (Java pours syntax vinegar over such a construct to discourage programmers from using it.)

Groovy control structures

Control structures allow a programming language to control the flow of execution through code. There are simple versions of everyday control structures like if-else, while, switch, and try-catch-finally in Groovy, just like in Java.

In conditionals, null is treated like false and so are empty strings, collections, and maps. The for loop has a for(i in x) { body } notation, where x can be anything that Groovy knows how to iterate through, such as an iterator, an enumeration, a collection, a range, a map -- or literally any object. In Groovy, the for loop is often replaced by iteration methods that take a closure argument. Listing 6 gives an overview.

Listing 6 Control structures
if (false) assert false     // #1 'if' as one-liner

if (null)                   // #2 Null is false
{                           // #3 Blocks may start on new line
    assert false
}
else
{
    assert true
}

def i = 0                   // #4 Classic 'while'
while (i < 10) {            // #4
    i++                     // #4
}                           // #4
assert i == 10              // #4

def clinks = 0                    // #5 'for' in 'range'
for (remainingGuests in 0..9) {   // #5
    clinks += remainingGuests     // #5
}                                 // #5
assert clinks == (10*9)/2         // #5

def list = [0, 1, 2, 3]           // #6 'for' in 'list'
for (j in list) {                 // #6
    assert j == list[j]           // #6
}                                 // #6

list.each() { item ->             // #7 'each' method with a closure
    assert item == list[item]     // #7
}                                 // #7

switch(3)  {                       // #8 Classic 'switch'
    case 1 : assert false; break   // #8
    case 3 : assert true;  break   // #8
    default: assert false          // #8
}                                  // #8


The code in listing 6 should be self-explanatory. Groovy control structures are reasonably close to Java's syntax.

That's it for the initial syntax presentation. You've got your feet wet with Groovy and you should have the impression that it is a nice mix of Java-friendly syntax elements with some new interesting twists.

Summary

You've got the first impression of Groovy's code notation and found it both similar to and distinct from Java at the same time. Groovy is similar with respect to defining classes, objects, and methods. It uses keywords, braces, brackets, and parentheses in a very similar fashion; however, Groovy's notation is more lightweight. It needs less scaffolding code, fewer declarations, and fewer lines of code to make the compiler happy. This may mean that you need to change the pace at which you read code: Groovy code says more in fewer lines, so you typically have to read more slowly, at least to start with.

About the Author

Dierk König is a senior software developer, mentor and coach. He publishes in leading German magazines on software development and speaks at international conferences. He works at Canoo Engineering AG, Basel, Switzerland, where he is fellow and founding partner. Since the first edition of this book came out, he has worked almost exclusively with Groovy, be it as an engineer, architect, consultant, or trainer. His single and multi-day trainings on Groovy and Grails attract lots of attention. He joined the Groovy project in 2004, working as a committer ever since.

Guillaume Laforge is the official Groovy Project Manager and Head of Groovy Development at SpringSource. He founded G2One, Inc. (later acquired by SpringSource), a professional services company dedicated to sustaining and leading the development of both Groovy and Grails. You can meet Guillaume at conferences around the world where he evangelizes the Groovy dynamic language, Domain-Specific Languages in Groovy, and the agile Grails web framework.

Dr. Paul King leads ASERT, an organization based in Brisbane, Australia which provides software development, training, and mentoring services to customers wanting to embrace new technologies, harness best practices and innovate. He has been contributing to open source projects for nearly 20 years and has been an active committer to Groovy since he joined the project in 2006. Paul speaks at international conferences, publishes in software magazines and journals. He has the pleasure of working with Groovy on a regular basis with many of his agile customers.

Jon Skeet is a Java developer working for Google in London. He is a C# author and community leader, spending far too much time on the Stack Overflow developer Q&A site. Jon's re-learning Groovy along the course of this book, standing in the readers' shoes and pulling up the rest of the authoring team if they steam ahead too quickly. His aim is to help to translate the experience and knowledge of the other authors into the most readable and informative text possible.


Tags: Groovy



Page 3 of 3



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel