TIL: Closures in Groovy

I interact with Groovy solely because Jenkins uses it to define pipelines.

Pros:

  • It’s in the Java ecosystem
  • It’s a “real” language (turing complete unlike YAML)
  • It’s not YAML

Cons:

  • No static typing
  • Linters/formatters aren’t great
  • Jenkins is quite hard to work with and has surprisingly poor tooling

While updating some Groovy scripts, I wanted to update a utiltiy method to take a closure in a nicer way. The method looked like this:

def hello(clo, first = "John", last = "Doe") {
    println "Hello, $first $last"
    clo()
}

// usage
foo(clo: { println "I didn't see you there!" }, first: "Jerred", last: "Shepherd")

I’ve seen methods that look a bit prettier when called, like this:

def bar(someArg, Closure clo) {
    clo()
}

bar(someArg) {
    println 'hello'
}

Note that the closure is passed as the last argument. This allows the closure to be passed in braces after the method call. This looks quite a bit nicer!

Inspired by Xe's blog

Originally, I wanted to combine named parameters, default parameters, and a closure as the last argument. Unfortunately, this doesn’t seem possible. Here’s what I came up with:

def baz(first = "John", last = "Doe", Closure clo) {
    println "Hello, $first $last"
    clo()
}

The result of running this:

baz(first: "Jerred", last: "Shepherd") {
  println "I didn't see you there!"
}
Hello, [first:Jerred, last:Shepherd] Doe
I didn't see you there!

Groovy implements named parameters as a map. Unfortunately, it seems that Groovy is using the both the first and last parameters as a map value and passing that to the first argument.

// Groovy takes this:
baz(first: "Jerred", last: "Shepherd")

// and implicitly converts it to this:
baz([first: "Jerred", last: "Shepherd"], null)

// so, when calling baz, we're passing the map as the first argument and null as the second argument
// this leads to Groovy using the map as the first argument, and the default value of "Doe" as the second argument
Hello, [first:Jerred, last:Shepherd] Doe
I didn't see you there!

// instead, we want Groovy to print:
Hello, Jerred Shepherd
I didn't see you there!

Closures are still pretty cool, but it’s frustrating to figure out the syntax for how some of these features interact. Additionally, the feedback loop for Groovy with Jenkins is long, so if you don’t know the language, it’s hard to make progress.

Recent posts from blogs that I like

Creating an already-completed asynchronous activity in C++/WinRT, part 4

Failing is easy. Failing correctly is hard. The post Creating an already-completed asynchronous activity in C++/WinRT, part 4 appeared first on The Old New Thing.

via The Old New Thing

Garlic and gravel

fragments

via Henrik Karlsson

My Glorious Ascension To Thought Leadership

I. This Escalated Quickly I mentioned one post ago that this blog has done approximately 2M+ lifetime views, with over a million of them being in the past two weeks in response to the now-infamous rant about AI, then I went out of my way to not write the most maximally viral thing possible for perso...

via Ludicity