Introduction

This guide is designed as an introduction to the Groovy programming language, for people without much, or any, previous experience of programming. Particularly, I hope to fill the niche for a Groovy learning resource which does not rely on any previous knowledge of Java. The importance of this, to me, is that I would recommend Groovy as a first language, while Java I would not - rather I believe Java impedes the gain of practical programming skills by being a somewhat disagreeable and unnecessarily difficult language.

However, the guide should also be suitable for those who have some previous experience with Java or other JVM languages, as it demonstrates the features and functionalities which are unique to the language, and should help you quickly reach the point of being able to create practical and useful programs using it.

Groovy is a language which works on the same ‘virtual machine’ as Java, which essentially just means that when you run it, it compiles into the same machine-runnable language as Java does.

It is an elegant and beautiful language; its features, some of which we will discover in this guide, and some you will find yourself, make it a worthy standalone programming language. It is flexible enough to be used both for ‘scripting’ and for programs which require lots of heavy-lifting.

Nevertheless, many of the objects and libraries you will end up using in Groovy in fact belong to Java, or are at least extended from the original Java objects.

This may seem confusing at first, as you may have to look up ‘JavaDoc’ or Java documentation when learning how to do a certain thing, but in the end you will realise that it is a great boon to be able to use the wealth of Java libraries and functionality without actually having to program in Java itself.

The guide starts by introducing the basic concepts of the language, and slowly moves onto more advanced topics. This will introduce you to the language, and then give you the understanding of the tools necessary to develop worthwhile programs using it. The guide is a work in progress, but as of now most of the basic concepts are covered, and I’m in the process of expanding it to include more in-depth topics.

Installation & Basic Usage

You can probably install Groovy from your package manager, or otherwise you can find out how to install groovy from their website.

In most cases, you will want to write your code into a text file, using your favourite text editor. I’ll leave it up to you to decide on this, but it can help to pick something with syntax highlighting.

Groovy files, by convention, are saved with a .groovy extension. Then, by command-line we execute these files with groovy filename.groovy.

There is also the Groovy shell, which is a useful tool for beginners and experts alike, to test the behaviour of certain small pieces of code on-the-fly. This can be extremely useful for debugging, or for simply exploring features of the language without having to write a full script. You can run the Groovy Shell by executing groovysh on the command-line.

First Steps

Once you have groovy installed, you can try writing the universal first-program, the ‘hello world.’ This is simple in Groovy, as it is in most languages:

println "Hello World"

You can either save this in a hello.groovy file and run it with groovy hello.groovy or you could type the code into the Groovy Shell and press enter. Either way, the results should be predictable. The println statement simply prints a line of output to the console.

Basics

Comments

Comments in Groovy are available in two varieties, the one-liner and the multiple-liner. Single line comments begin with //. Multiple line comments begin with /* and end with */ - anything between these two delimiters will not be executed by Groovy.

Comments usually come right before a particular piece of code which they explain or describe in natural language, generally describing what the piece of code does and what its intention is. They can be useful as a reminder for yourself, but they are especially useful for letting another person know what you were thinking when you wrote a piece of code.

The extent to which people use comments is variable, some arguing that they simply prefer to write idiomatic code. However, as a beginner, I recommend the heavy use of comments as a tool to help ‘translate’ your thinking into Groovy. Use a comment to explain what each step is doing, and think of the Groovy code which follows it as a ‘translation’ of your English thought into an instruction for the computer.

// This prints "Hello World" to the screen
println "Hello World"

As time goes on, certain operations will seem too simple and obvious to annotate, and it is likely your use of comments will become more discerning. Part of learning to program is learning to make your code understandable, and after a while you will only need to comment pieces of code you deem ‘necessary’ for explanation.

Variables

Variables are simply ‘names’ which refer to a certain piece of data, you can think of them as assigning a certain value to a ‘name,’ which you can then refer to in the rest of the program. As an example of this, we can extend our previous hello world example:

def myString = "Hello World"
println myString

As you can see, we first define a new variable with the name myString and assign to it the value “Hello World.” This is called variable assignment. The “Hello World” is known as a data literal.

Then we print it, and you will note that instead of passing a string directly to println, we have passed it a ‘name,’ which is a reference to the variable containing the string “Hello World.”

The def keyword must be used any time you define a new name to be used as a variable, and this is known as ‘declaring’ the variable. But, after this, we can change the value of the variable without the keyword, like so:

def myString = "Hello World"
println myString

myString = "I like turtles"
println myString

In this example, we first declare a new variable, myString, and assign to it the value “Hello World” - we print it, then we assign a new value to myString (note that we did not have to use def again) and print it.

As variable names, we usually use English language words which give some indication of what the variable contains. Notice that we do not surround the variable name with quotes. You cannot use certain words as variables, and these are usually words which are reserved by the language (we will be introduced to these as the tutorial continues). The first character of a variable name also cannot be a number, though numbers can appear elsewhere in the variable name.

Naming conventions for variables vary, but it is mainly important to be consistent either with yourself or with other peoples’ code you are working on. In this tutorial, I use the lower camel case convention, in which the first word of the variable is lowercased, and the following words are capitalised.

Functions

Functions are simply re-usable collections of code. We also assign these to variables, but in a slightly different way:

// Define a function to print Hello World
def helloWorld() {
  println "Hello World!"
}

// Call the Hello World function
helloWorld()
helloWorld()

Above, we create a new function and assign it to the name ‘helloWorld.’ Everything contained between the curly brackets { } is code which will be executed when the function is called - this is known as the closure.

We execute the function simply by invoking its name, followed by parentheses. As we can see by running this example, we can print two “Hello World!”s simply by calling the function we have designed twice. Functions are a powerful tool for reducing the amount of code we write, which centres around minimising the amount of code we have to repeat.

Another thing you may have noticed about the above example are the parentheses, both in the definition of the helloWorld function and on the two lines which call the helloWorld function. These are for ‘arguments,’ which are simply values we can pass to a function, and then the function can use for itself.

// Define a function to print something
def printSomething(thing) {
  println thing
}

// Print some things
printSomething("I like turtles")
printSomething("I like squirrels")

The first thing to note here is that we have added the word thing between the parentheses in the definition of the printSomething function definition. This means that when the function is called later, with a value between its own parentheses, this value will be available within the function closure bound to the thing variable name.

We can also pass multiple arguments to a function, like so:

// Define a function to print two things
def printTwoThings(thingOne, thingTwo) {
  println thingOne
  println thingTwo
}

// Print some things
printTwoThings("I like", "turtles")

Here we have extended the list of arguments accepted by the argument to two, and we print them when the function is called. A function can have as many arguments as it likes, but it is important to note that when you call the function, you must provide the correct amount of arguments stated in the arguments list of the function declaration (this is sometimes known as the prototype).

Function arguments are another important tool in programming, which further our ability to minimise code re-use. Our current examples seem trivial, but we will quickly see that we can use functions to perform complicated operations very easily and with a small amount of code.

Basic Data Types

Strings

We have already seen a few examples of the Groovy string, “Hello World” probably comes to mind. As you may have inferred from this already, strings in Groovy have to be surrounded by quotes. These can either be single quotes or double quotes , and there are some subtle differences, but the most important thing is to be consistent in which you choose to use.

We can use operators with strings, as we can with many data types, and the most simple of these is concatenation. Consider our last example, in which we defined a function to print two things to the screen. Let us now extend this to concatenate two strings together and print them on the same line.

// Define a function to print two things
def printTwoThings(thingOne, thingTwo) {
  def things = thingOne + " " + thingTwo
  println things
}

// Print some things
printTwoThings("I like", "turtles")

In this example, our function prototype and the way we call the function is the same, but inside the closure we do something a little different. We define a new variable, things, which uses the + operator to concatenate three strings together. Notice that it doesn’t matter whether we use variables or string literals, as the variables are simply references to strings themselves. The value of things will then be the concatenation of these three strings, which we can print to obtain the output “I like turtles”.

Numbers

Numbers are another common data type in Groovy, and its operators tend to behave in the same way as those in basic algebra.

// Define a function to add two numbers and print them
def addTwoNumbers(first, second) {
  def sum = first + second
  println sum
}

// Print some things
addTwoNumbers(3, 5)

In this example, we define a simple function to add two numbers, and print the result. We pass two literal numbers to the function, which adds these together and assigns the result to the sum variable, then printing it.

We should note here that operators behave differently, depending on the data type it is operating upon. We saw earlier, that the + operator concatenates strings, while here we observe that the + operator adds two numbers together.

Booleans

Booleans are very simple data types which can have only two values: true or false. While simple, these variables are useful when we want to give a ‘yes or no’ answer. We will save an example of the use of booleans for a little later, as their value only comes into play when we know how to use some more features of the language.

Data Types as Objects

The data types introduced above may seem a little dumb and simple, but now we will introduce a concept extremely important to Groovy: almost everything is an object. An object is simply a collection of things, which contain properties and methods. Properties are variables which belong to the object, while methods are functions which belong to the object.

There are many objects in Groovy, and later we will build even some ourselves, but first we must realise that even our most basic data types are also objects, which provide useful functions for working with them.

For now it is enough to understand that objects are instances of classes. Each object is an instance of a class, and a class is a definition of a certain type of object. This means that all objects of a certain type will share the same properties and methods.

Here we will also introduce documentation, and explain where to look if you want to know what an object can do, and what it contains.

Strings

The innocent-looking string literal in Groovy, is in fact an instance of a class called a String. Class names usually start with capital letter, to distinguish them from variables. To find out more about the String, we can look at documentation.

This page all looks a bit 90s and confusing, but in time you will learn to understand from them what is possible using an object of a certain class. For example, under the “Method Summary” heading, we can see a list of many functions and their prototypes. These define the functions belonging to every instance of the string, and which can be used on every instance of the string.

The first column describes the data type which the method returns, and in the second we find both a name of the function followed by its prototype (remember, these describe what values a function expects), and a short description of what the function does.

For example, the ‘length’ method returns an ‘int’ (though actually in Groovy it returns an Integer) and we are told that it returns the number of characters in a string.

println "I like turtles".length()
println "Built to Spill and Modest Mouse are great".length()

// Define a new string
def myString = "Sencha is delicious, but it's difficult to make right"
println myString.length()

// Create a new variable, containing the length of myString
def myLength = myString.length()
println myLength

Here, we invoke the length() method call on several strings. Note that we do this on both string literals, first, and then on variables with strings assigned to them. Both string literals and variables are known as expressions, and to invoke a method on them we simply have to follow them directly by a period, and then the function call. Think of these as similar to our earlier function examples, but as ‘belonging’ to the object.

We can also store the result of the method call in a variable, which we do at the end of the example. The value of myLength will be the length of myString, which is returned when .length() has been called on it.

Here we can also introduce our first use of the ‘boolean’ data type, by utilising the ‘contains’ method:

def myString = "I like turtles"

println myString.contains("turtles")
println myString.contains("biscuits")

In this example, we create a new string object, and then we invoke the contains method on it twice. From the Java String documentation above, we can see that the contains method returns a ‘boolean,’ with a value of either ‘true’ or ‘false’. We can think of functions or methods which return booleans like asking a question - for example, in the above example we first ask if myString contains the string “turtles”, and then we ask it if it also contains “biscuits”.

Numbers (Integers)

In a similar manner to strings, our number data type is also an object, of the class Integer. We can see the documentation for that here.

Again, we see a lot of information, including methods provided by the integer objects. Here, we will introduce an important example of a method which almost all objects provide, and which will prove useful when working with integers and will also give us a bit of insight into how other parts of groovy work.

Earlier we discussed how operators behave differently depending on their datatype. The particular example given that the + operator will concatenate strings, while it will add numbers together. So consider the following example:

// Concatenate two numbers
def concatenateNumbers(numberOne, numberTwo) {
  println numberOne + numberTwo
}

def firstNumber = 5 - 3
def secondNumber = 10 + 10

concatenateNumbers(firstNumber, secondNumber)

In this example, we define a function which we intend to concatenate two numbers. Then, we create two variables which are simple sums, and attempt to pass these to our function. The values we pass to our function are 2 and 20, so we expect our program to print “220”, but since these are numbers the + operator will add these together and print 22.

Of course, we could simply pass the literal strings “2” and “20” to our function, but then we would not be able to perform the mathematical operations we’ve used in defining our firstNumber and secondNumber. Generally, we are initially working with numbers as integers, performing various calculations on them, and then during the output stage we expect them to act as strings.

The way to fix this, is to use the toString() method:

// Concatenate two numbers
def concatenateNumbers(numberOne, numberTwo) {
  println numberOne.toString() + numberTwo.toString()
}

def firstNumber = 5 - 3
def secondNumber = 10 + 10

concatenateNumbers(firstNumber, secondNumber)

The toString method converts an object to its string representation, so our 2 and 20 will become “2” and “20” respectively, and then act as we expect. Most objects implement some form of toString function, and they are most often helpful when we want to convert our various data types into strings to prepare them for output.

Collections

Collections are another common type of object, which are often fundamental components of programs. There are two primary collection types which one will be concerned with when working with Groovy: the list and the map. Here I cover basic use of the two collection types, and in later sections we’ll go into more detail about the various ways they can be used. Either way, I recommend playing around with these structures and the examples a bit, and perhaps trying out some of the other methods described in the documentation yourself.

Lists

A list is simply a list of things, and is also commonly known as an array. The list stores objects sequentially, and can be accessed most basically through their integer indices. Like most other things in Groovy, lists too are themselves objects, and come with a rich toolset for their manipulation.

def myBand = "Volbeat"
def goodBands = [ "Die Aerzte", "Modest Mouse", "Oceansize", myBand ]

println goodBands[3]

goodBands.remove("Volbeat")
goodBands.add("Wilco")

println goodBands[3]

println myBand

This example first defines a list using what is known as the list literal notation, which is simply a list of objects with which to initialise a list with. We can either provide literal strings, as with “Modest Mouse”, “Die Aerzte” and “Oceansize,” or we can provide variable names, as with myBand. We can also create an empty list with a simple [ ].

After creating the list, we examine the third element. We do this using the square bracket notation, which contains the index of the element you want to retrieve. It is important to note that, unlike humans, computers generally start counting from 0 instead of 1, and so the ‘third’ item in our list is a reference to the variable myBand, which contains: “Volbeat”.

Our program doesn’t much care for the combination of metal with Elvis-style vocals, and so proceeds to remove Volbeat from the list of goodBands using the remove method of the list object. To fill the void, it adds its own choice using the add method: Wilco, clearly preferring its delightful country-inspired soft rock.

The remove method for lists in Groovy is very friendly, and will accept either a value or an index as an argument. This means we could have also used goodBands.remove(3) to achieve the same thing.

Then we examine the third element of the list again, and indeed it has been replaced by Wilco.

Next, an important demonstration - the removal of Volbeat from the list of goodBands did not destroy the myBand variable. If you add a variable to a list, you are only adding a reference, and if you remove it from the list, you are only removing that reference to it. You can remove a band from your playlist, but you can’t stop them existing.

Of course, if we had removed any of the other bands from the list, which were defined during the initialisation of the list, they would cease to exist for our purposes, since there would no longer be a reference to them anywhere in the program.

Maps

A map is another kind of data structure, similar to a list in that it holds objects, but instead of being keyed by a linear progression of integer indices, we use strings. In this way, we can attach data to a recognisable “key,” an easy example is a name.

def ages = [
  "reality": 23,
  "goedel": 45,
  "escher": 99,
  "bach": 33
]

println ages["reality"]

ages["escher"] = 21
println ages["escher"]

ages.remove("bach")

println ages.size()

In this example we define a map using the literal map notation, creating a list of key-value pairs. In doing this, we create a data structure in which values are indexed by their keys. Particularly, we associate some names with some ages - integers. We can also create an empty map using [ : ].

Then, similar to how we access items in lists, we look up reality’s age using the square bracket notation - with the difference that we use the string key we defined instead of an integer index.

We can also easily change the values contained in our map, using the familiar variable assignment notation. If Escher wishes to believe he’s only 21, he simply has to combine the square bracket notation with variable assignment to have our ages map believing it.

We then consider Bach, who wishes to remove his age from the map, and in another manner much similar to that of lists, we simply use the remove method with the key “bach” as a parameter. However, we should note that entries in maps are only available by their string key. Unlike lists, they have no order and so .remove(3) would not work.

However, it is not only our simple data types we can store in collections - any object will do. We can even embed lists (or even more maps!) inside our maps, to create more advanced data structures, like so:

def favouriteBands = [
  "reality": [ "Modest Mouse", "David Bowie", "Cyne" ],
  "socrates": [ "John Lennon", "David Bowie", "The Rolling Stones" ]
]

favouriteBands['zizek'] = [ "Daft Punk", "Emancipator", "Royksopp" ]

println favouriteBands['zizek'][2]

In this example, we first define favouriteBands map using the familiar literal map notation, except instead of simple integer values as in the previous example, we’ve used lists. After defining the list, we add a new list of favourite bands for Zizek, who rather enjoys his electronic music.

Afterwards, we access the last item in Zizek’s list by amending the square-bracket notation with another set of square brackets indicating the index in the list we want. This is linear, first we select Zizek’s list, then we select the last item from that list: Royksopp. This notation can be chained, and is available no matter the depth of the structure.

Control Flow

By using various constructs of the language, we can control its flow, and produce the results we require.

Conditionals

The conditional, often known as an if statement, is a way of evaluating a boolean expression and performing the code contained in its closure if the expression is true.

Extending our earlier example of the ‘contains’ method of the string object, we can use conditionals to perform code depending on the boolean result of the method:

def myString = "I like turtles"

if(myString.contains("turtles")) {
  println "My string contains turtles!"
}

def containsBiscuits = myString.contains("biscuits")
if(containsBiscuits) {
  println "My string contains biscuits!"
}

Here we observe an expansion of our earlier example, with two if statements. These are formed by the word if, followed by a parentheses which contains an expression which must evaluate to either true or false. In the case it is true, the closure which follows it will run, otherwise it will not. You can think of the basic ‘if’ statement a little like a function which accepts only one argument, true or false, which decides if the function runs or not.

The boolean expressions in our if statements can be extended by certain operators which allow us to form more complicated conditions:

def myString = "I like turtles"
def containsBiscuits = myString.contains("biscuits")

if(containsBiscuits && myString.contains("turtles")) {
  println "My string contains turtles!"
}

if(containsBiscuits || myString.contains("turtles")) {
  println "My string contains biscuits!"
}

In this example we use two new operators: && and ||, which are generally known as ‘and’ and ‘or.’ The first if statement requires that both of its parameters evaluate to true for the if statement to pass, while the second requires that only one of them is. These quite easily correllate to English phrases: “if contains biscuits or contains turtles”, “if contains biscuits and contains turtles”.

If statements can be elaborated upon even further, by providing an alternative closure to run in the case that the given boolean expression evaluates to false.

def myFavouriteGenres = [ "Hip Hop", "Bluegrass", "Alternative Math Rock" ]

if(myFavouriteGenres.contains("Big Room House")) {
  println "There is something very wrong!"
} else {
  println "Well, at least you're not into, like, Big Room House, or something."
}

In this case, we introduce a new keyword: else. Given directly after the end of the initial if closure, we can then provide another closure to be run in the case the first does not. In this case, myGenres is found not to contain “Big Room House”, and so our program expresses some pleasure at this (though I personally detect a hint of sarcasm in there).

Another conditional construct available is the combination of ‘if and else,’ known as an ‘else if’ statement. This is another boolean expression to be evaluated in the case that the first fails. We can chain these together as many times as we want, and then finally provide an unqualified ‘else’ statement for a closure to be run in the case all other cases are not satisfactory.

def myFavouriteGenres = [ "Alternative Rock", "Indie Rock", "Electro-swing" ]

if(myFavouriteGenres.contains("Hip Hop")) {
  println "I love Hip Hop!"
} else if(myFavouriteGenres.contains("Alternative Disco with Shoegaze Influence")) {
  println "That is like, literally, my favourite genre"
} else {
  println "I just don't think we can get along."
}

In this example we create a list of genres, and then our program, in an attempt to establish some common ground, looks in the list for “Hip Hop” - not finding it, it moves onto our ‘else if’ statement, in which it looks for “Alternative Disco with Shoegaze Influence” - if this were found the program would really express its happiness at having found some musical compatibility, but alas we must move onto the final ‘else’ statement.

It is important to note that these statements are evaluated linearly, if the first if statement returns true, the ‘else if’ statement will not be evaluated. Again, these constructs can quite easily be translated into English: “if my favourite genres contain Hip Hip, do this. Else, if my favourite genres contains Alternative Disco with Shoegaze Influence, do this. Else, I just don’t think we can get along.”

As well as testing the result of methods which return booleans, we also frequently make use of several other operators which help us decide if something should be true or false.

def myAge = 5
def myName = "Bertrand Russell"

if(myAge < 12) {
  println "Don't post comments on youtube"
} else if(myAge >= 75) {
  println "Don't go to youtube, you'll be horrified"
} else {
  println "You probably shouldn't post comments on youtube anyway"
}

if(myName == "Bertrand Russell") {
  println "Proof is a necessarily weaker notion than truth!"
}

if(myName != "Zizek") {
  println "Enjoy Coca Cola!"
}

In this example we see the introduction of several new operators we can use in the boolean expressions for our if statements. These work in exactly the same way as the operators we’ve seen before, such as +, except instead of concatenation or addition, they return a boolean result: either true or false.

Our first is the < operator, which simply means ‘less than.’ If myAge is less than 12, we order one not to post on YouTube. Inversely, there is also the > operator, which is ‘greater than.’

In our else if expression, we use >=, which is similar to the greater than operator, but means ‘greater than or equal to.’ Again, we have the inverse <= for less than or equal to.

In our next if statement, we introduce the == operator, which means ‘equals.’ At first it can be easy to confuse this with the = operator, which we use for variable assignment, but the == operator checks if two objects have the same value. In our example, we check if myName is equal to “Bertrand Russell”, and if so give him a fright by debasing the foundational conception at the centre of his life’s work.

Our next if statement is the opposite of the == operator, != means ‘not equals.’ So, our expression evaluates to true if the two objects have distinct values. Zizek doesn’t enjoy Coca-Cola, and we wouldn’t want to upset him.

While we have introduced some new symbols here, one can realise that operators are, in fact, just functions which use an in-fix (one argument on either side of the operator) notation instead of the usual parametised notation. These symbols exist for clarity of understanding expressions. For example, for our == operator we will find a correspondent equals method in the documentation for the string object. This means we could have achieved the same thing by using myName.equals(“Bertrand Russell”) as the if statement argument.

This also illustrates that, like our other operators, boolean operators will also behave differently depending on the object type. For example, “5” == 5 will evaluate to false.

Loops

Often, we will want to perform an action repeatedly. This need can arise for many purposes, for example to repeat an action until a condition is reached, or to iterate through a collection.

While

The while statement can be thought of as a closure which will repeatedly execute its contents until the condition it is given has been satisfied. Like an if statement, it accepts one argument of a boolean expression which evaluates to true or false.

def count = 0

while(count < 5) {
  count = count + 1
  println "Added 1 to " + count + "!"
}

println "We counted to five!"

In this simple example, we initialise a variable count with the value 0, then we include our while statement. Its argument uses the ‘less than’ operator to test if count is less than 5. Much like an if statement, the closure will execute only if the evaluation returns as true. The major difference, is that the closure will run repeatedly, until the condition is satisfied. In each of our iterations, we add 1 to our count until eventually it is no longer less than five, and we proceed to print our statement of victory.

Collection Iteration

For many languages, we would likely cover the ‘for’ statement at this point, and while this still has some use cases in Groovy, we generally have much better provision for iteration over collections. There are many powerful and interesting things we can do with these functions provided by Groovy, but first we will cover the most simple, the ‘each.’ Each is a method, similar to those we have seen previously, but instead of a parenthetical list of arguments we pass it a closure.

def biscuits = [ "rich tea", "digestive", "hobknobs" ]

println "We have the following kinds of biscuit: "
biscuits.each { biscuit ->
  println biscuit
}

First we define a list of biscuits, and then by using the ‘each’ method with its associated closure, we iterate every element in the list of biscuits, printing it. Directly after the beginning of the closure, we can use a variable name followed by a -> operator, to bind the current element being processed to a variable name, in this case ‘biscuit.’

We can iterate maps in a similar way:

def favouriteBands = [
  "reality": [ "Modest Mouse", "David Bowie", "Cyne" ],
  "socrates": [ "John Lennon", "David Bowie", "The Rolling Stones" ],
  "zizek": [ "Daft Punk", "Emancipator", "Royksopp" ]
]

favouriteBands.each { person, bands ->
  println "The favourite bands of " + person + " are " + bands.join(', ')
}

In this example we reuse our map of favourite bands, and use the each method to iterate it. The main difference here, is that when we define our variable bindings for the closure, we provide two: one for the key and one for the value. We then use the join method of List to create a comma-delimited list of each person’s favourite bands.

Recursion

Another option we have for looping is recursion, which we generally achieve through having a function call itself, until some condition is met.

def fibonnaci(n) {
  if(n <= 2) {
    return 1
  } else {
    return fibonnaci(n - 1) + fibonnaci(n - 2)
  }
}

println fibonnaci(4)
println fibonnaci(5)

In this example, we define a simple recursive function to find a given number in the famous Fibonnaci Sequence.

In the Fibonnaci sequence, we find the next Fibonacci number by adding the last two Fibonnaci numbers together. In our approach, we work backwards from our target number in the fibonnaci sequence by computing the previous numbers.

First, we test if our argument is less than or equal to two, in which we return 1, because the first two Fibonnaci numbers are 1. Otherwise, we return the sum of the last two Fibonnaci numbers - which we, in turn, find by calling the fibonnaci function. So our function executes like so:

  1. fibonnaci(4) is called
  2. 4 is greater than 2, so we return fibonacci(3) + fibonnaci(2)
    1. fibonnaci(3) is called
      1. 3 is greater than 2, so we return fibonnaci(2) + fibonnaci(1)
        1. fibonnaci(2) is called
        2. 2 is less than or equal to 2, so we return 1
        3. fibonacci(1) is called
        4. 1 is less than or equal to 2, so we return 1
      2. We add the results of fibonacci(2) and fibonacci(1), 1+1 and return 2
    2. fibonnaci(2) is called
      1. 2 is less than or equal to 2, so we return 1
  3. We add the results of fibonnaci(3) and fibonacci(2), 2+1, and return 3

Recursive functions can be difficult to follow at first, but they can be a powerful tool for simply expressing otherwise difficult and complicated algorithms.

Basic Classes

In this section we will discuss the basics of ‘object orientated programming,’ which is the practice of building and using objects in our programs. They allow us to conceptually model and design our programs quite easily and in a ‘human-understandable’ way, as well as to create re-usable pieces of code across multiple programs.

As we explained earlier, classes are definitions of objects. Objects are instances of a class, and each of them has properties (data) and methods (functions) according to its class definition. We have seen several examples of classes and objects so far, and we must remember that even the simplest data types in Groovy are themselves objects. But now, let’s try making our own class.

class Person {
  def name

  def sayName() {
    println "Hello, my name is " + name 
  }

  def say(thing) {
    println name + " says '" + thing + "'"
  }
}

def plato = new Person()

plato.name = "Plato"

plato.sayName()
plato.say("The law of nature is the law of the stronger!")

In this example, we create a new class, called Person. Instead of using the ‘def’ keyword as we usually do, here we use the class keyword to start defining a class, we follow it by the name of the class. Conventionally, people capitalise class names so they can easily be told apart from regular variable names.

In the class closure, we declare some variables which should belong to this class, and here we add ‘name.’ You will notice that this ‘def name’ doesn’t include a variable assignment - this isn’t necessary, and by omitting it we are only declaring the name as one we want to use at some point later in the program. Then, we declare some functions; this is done in the exact same way as we have been declaring functions normally, except that in this case we are defining the functions inside the class and thus every instance or object of that class will have these functions, as they will have the ‘name’ variable.

After we finish defining our new class, we set out to create a new instance of it. To do this, we create a new Person() and assign it to the variable plato. Now, we have an object of the class Person. Just as “fish” would be an object of the class String.

We can access the properties and methods of objects by following the variable with a dot, and to start with we give our brand new person a name with simple variable assignment. This sets the internal ‘name’ variable of our Person instance to ‘Plato.’

Then, we invoke some methods on the Person class. First, sayName. You will notice that the sayName method has no arguments, and inside its definition we simply refer to ‘name.’ This is possible because all methods of a class have access to the variables belonging to the class which contains it - this is known as its scope.

We also invoke our say method, in which we pass a string containing one of Plato’s utopian proclamations.

As we have seen above, methods of classes have access to the variables in their scope, but they also have access to the methods in their scope. Because of this, we can simplify our code:

class Person {
  def name

  def sayName() {
    say("Hello, my name is " + name)
  }

  def say(thing) {
    println name + " says '" + thing + "'"
  }
}

def plato = new Person()

plato.name = "Plato"

plato.sayName()

In this example, our only difference is that the definition of sayName simply calls the internal ‘say’ method of the Person, instead of utilising ‘println’ itself. In this way, we only have to define how our Person will say something once, and in doing so reduce our code repetition.

It is also a little clunky to have to manually set our Person’s name after making the new Person. Instead, we can utilise what is known as Groovy’s default constructor:

class Person {
  def name
  def age

  def sayName() {
    say("Hello, my name is " + name)
  }

  def say(thing) {
    println name + " says '" + thing + "'"
  }
}

def plato = new Person('name': 'Plato', 'age': 23)

plato.sayName()

Here, instead of setting Plato’s name manually, we define it in the parameters when we are creating our new Person. As you can see, we can pass a list of arguments, which are key-value pairs (exactly like those in when we are defining our maps). These will automatically correlate to the variables we’ve defined at the top of our class closure, and assign the values we pass to them upon the object’s creation.

There is a lot more we can do with classes, but this basic introduction should give you an understanding that we can create our own collections of properties and methods like String and Integer. The only real difference between our Person class and classes like String and Integer is that they are recognised by the language and given special syntactic sugar to make them easier to use. But in fact, they are the same.

def oneString = "I like turtles"
def twoString = new String("I like turtles")

println oneString
println twoString

Here we see two ways of creating an instance of string. The first, which we have seen earlier in the tutorial is the easy way of doing it, but the second uses a syntax much like the one we have seen when creating new instances of our Person object. They are the same.

Libraries

Now we have covered many of the basic language constructs, which are the foundational tools we will use to create useful programs, we will now introduce the idea of including external libraries. We will cover how to find and import a library, and later introduce some common libraries which should allow you to begin making useful programs.

You can think of a library in Groovy as something which simply provides you more classes and objects to use. Like our Map, our List and our String, the objects libraries provide will have methods and properties of their own, and will provide functionality for you to use in your program.

Groovy has a very easy and usable dependency system, unlike its cousin. Groovy is linked to something called the ‘Maven Repository,’ which is a library of Java dependencies we can easily import and use in our programs.

For our example, imagine that we are trying to produce a program which requires the use of a random string. This is a common requirement for programs, and we could likely create something to do this ourselves quite easily, but this in itself is a good indicator that someone else has likely done it before, and better.

In such a case, we might try to look for a library to achieve what we want. Generally, the Maven Repository itself isn’t a great place to do this, as its search functionality mostly centres around the names of the packages themselves. However, through Google we might find a page like this, which describes how to generate a random string using the Apache RandomStringUtils class.

If we search the RandomStringUtils class, we will find its documentation, which describes the object and importantly for us will provide what is known as its ‘class path.’ Every object in Java has a ‘class path,’ which can be considered as a sort of unique location for the class. A library will generally have one class path, which can be considered as a ‘folder’ or ‘package’ of the classes it contains. At the top of this page, we can see that the class path for our target RandomStringUtils class is ‘org.apache.commons.lang3.RandomStringUtils’.

Still, Maven directly won’t help us much here but we can Google ‘maven org.apache.commons.lang3.RandomStringUtils’ to find this page, which is the library we’re looking for.

This process may seem arduous and horribly inspecific, and sometimes it is. Finding the right library and how to include it can be difficult, and there remains to be some easier way to find the functionality you want. However, though it is often joked about, learning how to use Google is a serious part of learning how to program. You need to be able to track down the libraries you need. This becomes a sort of innate ability over time, and becomes less stressful when you fall into a pattern of using similar libraries, with some good memory of what certain libraries provide.

So, we have this page, and under some information we have some tabs including various ways to include this library in our program. The one we want is ‘Grape;’ the name of the packaging system in Groovy. So we can swap to that tab, and copy it into the top of our program.

@Grapes(
  @Grab(group='org.apache.commons', module='commons-lang3', version='3.0')
)

import org.apache.commons.lang3.RandomStringUtils

println RandomStringUtils.randomAlphanumeric(5)

At the top of the example, we have our ‘grapes’ declaration, and this can be extended with a comma delimited list of ‘grapes.’ When the script starts, the groovy interpreter will read these statements and automatically download any libraries which haven’t been already. These should always be placed at the top of your script.

Then, we need to actually include the class we want to use in the script. This is done with the ‘import’ statement, and these must come before any use of the given class in the script - though by convention they go at the top of the script, after the ‘Grapes’ statement but before any of your code. The import path corresponds to the classpath of the class we want, as we found in the documentation earlier.

After importing the class, it’s available in our script, and we can use it. We’ve also introduced one new construct here, and this is the use of a static method. These are methods which belong to a class, but you call them directly from the class itself, instead of on an instance or object of the class. These are generally used when there is no need for an ‘instance’ of the class. Our call to the static method of the RandomStringUtils class will give us a random string five alphanumeric characters long.

Writing and Reading from Files

Thus far we have seen how to import transform and work with data in the form of maps, lists and simple literals, but to create useful programs we must be able to interact with files - both to read input and to save output. In this way, we can make meaningful changes to data, and then save these to files.

Reading a File

Reading a file in groovy is tremendously easy, and can be done without the use of any libraries which aren’t already available when you run your script.

def myTurtles = new File("turtles.txt").text
print myTurtles

In this file, turtles.txt, say we have a list of different kinds of turtles - one on each line. This example assigns the full text of the turtles.txt file as a string to the myTurtles variable, and then prints it out. We do this by creating a new instance of the File class, with a parameter containing the path to the file in our local filesystem. Creating this object reads the file, and then we access the ‘text’ property of the newly created file object to obtain the text of the file.

You can also see that we’ve taken a certain liberty here in simply accessing the property of the new object instance on the same line, instead of first assigning it to a variable. This is possible, and preferable in cases where you don’t actually need to do anything further with the class (since note, we will no longer have any access to the File instance itself, only the text property which we have assigned to the variable).

In many cases simply sticking the whole text of a file into a string might not be all that useful. The File object can operate in a very similar manner to a list in that we can iterate through them using a closured method.

def myTurtles = []

new File("turtles.txt").eachLine { turtle ->
  myTurtles << turtle 
}

myTurtles.each { turtle ->
  println "One kind of turtle is " + turtle
}

In this example, we first create a new empty list, and assign it to myTurtles. We then create a new File instance, but instead of reading all its text in one go, we use the eachLine method of the file object to provide a closure to run on each line of text in the file.

In this closure, we observe a new operator: «. This simply means ‘add to list’, and its equivalent method is .add(turtle).

Then we have a regular list populated with our turtles - one entry for each line, or each turtle. We iterate over this in the same way as we have seen before, and print out each kind of turtle.

Writing a File

Writing a file is similarly easy in Groovy.

def myTurtles = [ "red eared slider", "common musk turtle", "snapper turtle" ]

def myTurtlesFile = new File("turtles.txt")

myTurtles.each { turtle ->
  myTurtlesFile << turtles + "\n"
}

In this example, we start by defining a small list of types of turtle, then we create a new File instance. Note, it doesn’t matter if the file actually exists or not - since the File object is used both for reading and writing. However, you should be aware that if you open a File object and then write to it, it will append any existing file that was there in its place.

We then iterate through our turtles list, and for each turtle we write a new line to the file with the type of turtle. Note we have another instance of the « operator here, which when applied to a file means ‘write to the file’ - its equivalent method is .write(turtle). We also concatenate a “\n” to our line - this is ‘special character’ generally recognised by all computer software, meaning ‘add a new line here.’

JSON

JSON is a data format which is essentially designed to serialise maps. That means, you can read JSON documents directly into a map in your software, then you can serialise that map into JSON format and save it into a file. A lot of data is stored in this way, and it’s an easy way to persist data across sessions, to create a database, to create data in a way which is easy for yourself or others to manipulate.

We’ll cover the two basic use cases here, but you can read more about the classes Groovy has available for handling JSON documents here.

Writing JSON

Groovy has included extremely simple classes for manipulating JSON documents, and we will start by creating a simple JSON document from a map:

import groovy.json.JsonBuilder
 
def favouriteBands = [
  "reality": [ "Modest Mouse", "Built to Spill", "Cyne" ],
  "socrates": [ "John Lennon", "David Bowie", "The Rolling Stones" ],
  "zizek": [ "Daft Punk", "Emancipator", "Royksopp" ]
]
 
new File('favourite_bands.json') << new JsonBuilder(favouriteBands).toPrettyString()

First, we have to import the ‘JsonBuilder’ class from the groovy.json package, so we can use it in our script. Note that we don’t have to download this using a Grape, since the package is available by default in Groovy.

Then, we establish our familiar favouriteBands map of lists, noticing that reality has replaced David Bowie by Built to Spill in his list, for now, because he’s on an intense 90s alternative rock kick.

Then, we create a new File object, noting that again we don’t bother assigning it to a variable, since we’re only using it on this one line. Again, we use the « operator to write something to the file. Then, on the right side of the operator, we create a new JsonBuilder instance, passing our map as a parameter. This creates a JSON representation of our map, which we then invoke the toPrettyString method on, to create a string we can write to our file (you could also use toString, but then the resulting JSON document would be more difficult to read!).

After running this, we can examine our favourite_bands.json file to see something like this:

{    
    "reality": [
        "Modest Mouse",
        "Built to Spill",
        "Cyne"
    ],
    "socrates": [
        "John Lennon",
        "David Bowie",
        "The Rolling Stones"
    ],
    "zizek": [
        "Daft Punk",
        "Emancipator",
        "Royksopp"
    ]
}

You should be able to see that this generally corresponds to the map we defined in our program. However, saved in this file, our data structure is now available for manipulation by anyone, using any (decent) programming language.

Reading JSON

Reading JSON files is just as easy, and now that we have serialised our map into a favourite_bands.json file, we can just as easily read it back into a program and make it available as a map. And in this example we will not only read a JSON file, but we will modify it and save it again, showing how we can write scripts to transform and then save data persistently.

import groovy.json.\*

def bandsFile = new File('favourite_bands.json')
def favouriteBands = new JsonSlurper().parseText(bandsFile.text)

println favouriteBands['zizek']

favouriteBands.each { name, bands ->
  bands << 'Radiohead'
}

bandsFile.text = new JsonBuilder(favouriteBands).toPrettyString()

In this example we immediately see something slightly new. Earlier I described classpaths as being a little like folders, and so if you wish to use several or all of the classes in one package, you can simply include the classpath appended with a .*, instead of the fully qualified name of the class. We have done this here, because we wish to use both JsonBuilder and JsonSlurper in this script, and they both reside in the same package.

Then, we create a new instance of the File object, with the favourite_bands.json file created earlier. Then, we create a new instance of the JsonSlurper class, and then use the parseText method, passing it the text property of our file.

Printing Zizek’s favourite bands verifies that we have our map just as we expected it, and just as we saved it. After doing this, our script rather scrupulously adds Radiohead to everyone’s list of favourite bands, and this is all done in a manner that should be familiar to you now.

Then, we simply create a new pretty string representation of the modified favouriteBands and set it to the text attribute of the file. You should be able to open the favourite_bands.json file again to confirm that indeed, everybody loves Radiohead - and with good reason.

HTTP Requests

Fortunately, we don’t have to create all the JSON we want ourselves. There is a lot of data to be found on the Internet for us to play around with to be found in JSON format, and being able to receive it is in some senses the final step in being able to create useful programs which retrieve data, transform them, and create new data.

To do this, we need to be able to make HTTP requests - that is, to be able to retrieve data from the Internet. To do this, we can use the glorious Groovy library: HTTPBuilder. To teach us this library, and to put some of the skills we’ve accrued to the test, we’ll build a simple application to search Wikipedia, which has an open JSON API.

@Grab(group='org.codehaus.groovy.modules.http-builder', module='http-builder', version='0.7' )

import groovyx.net.http.HTTPBuilder
import groovy.json.JsonBuilder

new HTTPBuilder('https://en.wikipedia.org/w/api.php').get(
  'query': [
    'action': 'opensearch',
    'search': 'john frusciante'
  ]
) { resp, json ->
  if(resp.status == 200) {
    def responseFile = new File('john_search.json') 
    responseFile.text =  new JsonBuilder(json).toPrettyString()
  } else {
    println 'Something went wrong :('
  }
}

This example may initially seem a little confusing, but actually we are only using functionality we have used before - with the addition of the HTTPBuilder class. First, we use the @Grab line to install the dependency, and then we import our JSONBuilder class along with the HTTPBuilder class.

Following this, we create a new instance of the HTTPBuilder class, passing the endpoint for the Wikipedia API to it as a parameter. Wasting no time with binding it to a variable, we invoke the ‘get’ method on it, and in a manner equivalent to our groovy default constructor, we use a list of key value pairs as parameters to the get request.

[
    "john frusciante",
    [    
        "John Frusciante",
        "John Frusciante discography",
        "John Frusciante EP",
        "John Frusciante & Omar Rodriguez-Lopez"
    ],   
    [
        "John Anthony Frusciante (/fru\u02d0\u02c8\u0283\u0251\u02d0nte\u026a/; born March 5, 1970) is an American guitarist, singer, producer and composer.",
        "The discography of John Frusciante, who is best known as the former guitarist of the rock band Red Hot Chili Peppers, consists of eleven solo albums and four EPs, as well as two albums with collaborators Joe Lally and Josh Klinghoffer under the name Ataxia and one EP and one album under the alias of Trickfinger.",
        "This is a redirect from an album to a related topic such as the recording artist. For more information follow the bold category link.",
        ""
    ],   
    [    
        "https://en.wikipedia.org/wiki/John_Frusciante",
        "https://en.wikipedia.org/wiki/John_Frusciante_discography",
        "https://en.wikipedia.org/wiki/John_Frusciante_EP",
        "https://en.wikipedia.org/wiki/John_Frusciante_%26_Omar_Rodriguez-Lopez"
    ]    
]

More to come!