Step 1 of 5 · Reading · ~2 min
Learn
Collections and Closures
Closures are first-class blocks of code that keep access to the variables around them. They are written with { ... } and they turn up everywhere in Groovy:
def twice = { x -> x * 2 }
twice(5) // 10
// implicit `it` for a single argument
def triple = { it * 3 }
triple(5) // 15
// multi-arg
def add = { a, b -> a + b }
add(3, 4) // 7
Name your closures carefully: double, int, float and friends are Java type keywords, so def double = { x -> x * 2 } is a compile error (Unexpected input: 'def double ='), not a closure.
Closures are why Gradle build scripts look the way they do — every task { } block is a closure being handed to a method.
Currying fixes the leading arguments and hands back a smaller closure:
def multiply = { a, b -> a * b }
def dbl = multiply.curry(2)
dbl(7) // 14
with runs a closure against an object as the receiver, so you can drop the repeated variable name:
new StringBuilder().with {
append("Hello")
append(", ")
append("world")
toString() // the block's value is the last expression
}
The trap: an empty result is not zero
findAll returns a list, and sum() on an empty list returns null, not 0:
[1, 2].findAll { it > 10 }.sum() // null, and prints as null
[1, 2].findAll { it > 10 }.sum() ?: 0 // 0
The Elvis operator ?: supplies the fallback. This exact case is one of the tests in the exercise below.
Your exercise
Filter a line of integers with a closure and total what survives. The mistake the grader catches is printing null for the line where nothing is greater than 10.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…