An extension for Groovy Lists – a less strict alternative for first(), last(), etc.

A follow-on from my earlier post An extension for Groovy Lists – getting the only element of a List

A common use case (for me, at least)

I have often found myself with cases where I want to try to get an element from a list knowing that the later code will behave as expected, regardless of whether the element was present or not. An example of this:

if (!playersStillToPlay.isEmpty()) {
    currentPlayer = playersStillToPlay.head()
    playersStillToPlay = playersStillToPlay.tail()
}
else {
    currentPlayer = null  // Needs to be null if playersStillToPlay was an empty list
                          // If playersStillToPlay was empty it doesn't matter what playersStillToPlay is after this point so I don't change it
}

if (currentPlayer) {
    // Do the things
    // Use value of playersStillToPlay
}

To suit this type of situation I wanted versions of first(), last(), etc. which were a bit more loose. Specifically, I wanted versions that wouldn’t throw a NoSuchElementException if the list is empty.

My solution: xIfAny()

So the way to achieve this, which I think best fits with the existing methods and the idea of having expressive method names, was to have companion methods named xIfAny(). So into my Groovy extension library I added the following methods: firstIfAny(), lastIfAny(), headIfAny(), tailIfAny(), and -to match my new only() method- onlyIfAny().

So the above code snippet can now be tidied-up to become:

currentPlayer = playersStillToPlay.headIfAny()
playersStillToPlay = playersStillToPlay.tailIfAny()

if (currentPlayer) {
    // Do the things
    // Use value of playersStillToPlay
}

Some considerations

There were two cases where I needed to think about how to handle these new methods properly.

tailIfAny()

I needed to decide how tailIfAny() should behave if you call it on an empty list. I feel that it would be handy to return an empty list. That way you can always call each() or some other function on the result safely. However, for consistency with the other methods, I decided that it should return null. I can always add a new method which will return an empty list and name it differently to explain the different behaviour.

onlyIfAny()

Ironically perhaps, of all the methods I was extending in this way it was my method that seemed most odd. Calling only() indicates that you know that there is one, and only one, element in the list. So then onlyIfAny() means you know that there is at most one element. However, all of these extension methods are about loosening the constraints from the original methods so I am still happy with the extra functionality it gives you, even though it may seem a touch odd.

More info

The GitHub repo for the library: https://github.com/dnahodil/groovy-extra-list-behaviour.
A follow-up post explaining how to use my extension library in a Grails application

Leave a comment