Feature or Bug, You Decide: Argument Reordering in Groovy August 19, 2008 | 04:52 am

[Edit: Some documentation has been added to clarify this issue — see Groovy’s Extended Guide to Method Signatures on the wiki. And now that I’ve read through the documentation and grok the way that Groovy is intending to work, I actually like it. At first, though, it was a bit of a nasty shock.]

Running this in the groovyConsole:

void custom(Class cls, Map args) { println cls.name + " " + args }
custom(Integer.class, foo:"Bar!")

Explodes like this:

groovy.lang.MissingMethodException: No signature of 
method: Script3.custom() is applicable for argument 
types: (java.util.LinkedHashMap, java.lang.Class) 
values: {[foo:Bar!], class java.lang.Integer}
at Script3.run(Script3:5)

I expect the explosion, but it looks like the types of my arguments are getting swapped around before it explodes. In fact, if I swap the order of the arguments around at the call site…

void custom2(Map args, Class cls) { println cls.name + " " + args }
custom2(Integer.class, foo:"Bar!")

…the code runs without a hitch.

It turns out that Groovy intentionally reorganizes arguments passed into a method for you, beginning with the naked map, then normal arguments, then varargs.

More at my (closed, “Not a Bug” JIRA ticket): GROOVY-3006. See also Groovy-3009 for more issues with method reordering.

Tags: ,

  • http://insidethemachine.wordpress.com Josh

    I read the JIRA tickets and the documentation, but I’m failing to see why this reordering is a good thing. What am I missing? Why do you like it?

  • http://www.linkedin.com/in/robertfischer Robert Fischer

    By rearranging the arguments, you can play fast-and-loose with your API. For instance, I could call custom(class, prop1:”val1″, prop2:”val2″), or I could call custom(prop1:”val1″, prop2:”val2″, class).

    This actually makes life easier for people constructing builders, because you can specify “required” values, allow the user to put the map where they like, and collect everything that’s left as varargs.

    To allow that kind of flexibility through the traditional Java API would require a plethora of carefully-wired methods. Given defaulted parameters, it’s actually clearer to the developer and easier on the user to allow the flexibility. And, of course, if you’re the user and you want to be anal about it, you can always use explicit maps to force the argument order.

    Once you get used to the idea, it’s actually pretty nice. Reminds me a bit of Perl’s pseudohashes, but cooler.

    The only thing is that I wish they would enforce the closure constraint if I’m expecting to be passed a block. It seems like an odd decision to force that into userspace while everything else is taken out up front.