Define Groovy closure with kwargs and varargs

Viewed 1265

I've come across an inconsistency between Groovy functions and closures that has me stumped.

I can define a function with signature def foo(Map kwargs=[:], ... varargs){...} that does pretty much exactly what I expect it to. It takes pretty much every named and unnamed argument I give it. It also takes no arguments and works correctly.

I cannot find a similar way of defining a closure that has an identical signature. As a quick demonstration, when I run the following four lines:

def foo(Map kwargs=[:], ...args ){"kwargs=${kwargs.toString()} args=${args.toString()}"}
def bar = { Map kwargs=[:], ...args -> "kwargs=${kwargs.toString()} args=${args.toString()}"}
println foo(1:1,2:2)
println bar(1:1,2:2)

I get the following output:

> groovy test.groovy
kwargs=[1:1, 2:2] args=[]
Caught: groovy.lang.MissingMethodException: No signature of method: test$_run_closure1.call() is applicable for argument types: (java.util.LinkedHashMap) values: [[1:1, 2:2]]
Possible solutions: any(), any(), doCall([Ljava.lang.Object;), any(groovy.lang.Closure), each(groovy.lang.Closure), any(groovy.lang.Closure) groovy.lang.MissingMethodException: No signature of method: test$_run_closure1.call() is applicable for argument types: (java.util.LinkedHashMap) values: [[1:1, 2:2]]
Possible solutions: any(), any(), doCall([Ljava.lang.Object;), any(groovy.lang.Closure), each(groovy.lang.Closure), any(groovy.lang.Closure)
    at test.run(test.groovy:4)

Running with Groovy Version: 1.8.6 JVM: 1.8.0_131 Vendor: Oracle Corporation OS: Linux

I would like to write a closure that can take any number of named or unnamed arguments, including no arguments at all. Is this possible?

2 Answers
Related