After reading Mixing dynamic and static code in Groovy I learned about the implicit method available in a closure: doCall(). This method corresponds to the arguments and body of the closure. If we invoke a closure with the call() or the unnamed () syntax the doCall() method is invoked. We can use this method to run the closure from within the closure.
def sizeList = { list, counter = 0 ->
if (list.size() == 0) {
counter
} else {
doCall(list.tail(), counter + 1) // Call closure self.
}
}
assert 5 == sizeList([1,2,3,4,5])