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

The case of the missing ordinal 380

Untangling the error message and developing a theory. The post The case of the missing ordinal 380 appeared first on The Old New Thing.

via The Old New Thing

"No way to prevent this" say users of only language where this regularly happens

In the hours following the release of CVE-2024-38063 for the project Microsoft Windows, site reliability workers and systems administrators scrambled to desperately rebuild and patch all their systems to fix a vulnerability where a specially crafted IPv6 packet can result in remote code execution.....

via Xe Iaso

Thinking about perceptiveness

links

via Henrik Karlsson