Alexandru Popescu ☀ wrote:
Python supports the following format:
positional arguments
*args:
**args: named parameters
This seems to work oke there. But I don't think that mixing them makes sense.
Python is very explicit that **kwargs must be last and *args must be last (or second to last when **kwargs is last).
In Groovy it is possible to simulate some of the positional/named arguments that Python supports. For instance:
def mymethod(arg1, arg2, List args=[], Map kwargs=[:]) {
println "arg1: $arg1, arg2: $arg2, args: $args, kwargs: $kwargs"
}
groovy> mymethod('hello', 'world')
arg1: hello, arg2: world, args: [], kwargs: [:]
groovy> mymethod('hello', 'world', ['from', 'list'])
arg1: hello, arg2: world, args: ["from", "list"], kwargs: [:]
groovy> mymethod('hello', 'world', ['from', 'list'], [from: 'kwargs'])
arg1: hello, arg2: world, args: ["from", "list"], kwargs: ["from":"kwargs"]
I don't have to explain to this list that this is accomplished by compiling the above method definition down to three methods but will do so to illustrate a point. The following signatures are generated in bytecode:
Object mymethod(Object arg1, Object arg2, List args, Map kwargs)
Object mymethod(Object arg1, Object arg2, List args)
Object mymethod(Object arg1, Object arg2)
Should the inverse of the spread operator (i.e. something akin to 'collect') be introduced for method/closure arguments? If spread is used in a method or closure argument definition, it indicates that it is optional (i.e. args=[], kwargs=[:]) and that the arguments are to be interpreted a certain way. 'Overflow' positional args are rounded up into a List and named args into a Map. For instance, borrowing from Python, could the following syntax (* for positional and ** for named arguments) be introduced that enable the subsequent method calls?
def mymethod(arg1, arg2, *args, **kwargs) { ... }
groovy> mymethod('hello', 'world')
arg1: hello, arg2: world, args: [], kwargs: [:]
groovy> mymethod('hello', 'world', 'from', 'list')
arg1: hello, arg2: world, args: ["from", "list"], kwargs: [:]
groovy> mymethod('hello', 'world', 'from', 'list', from: 'kwargs')
arg1: hello, arg2: world, args: ["from", "list"], kwargs: ["from":"kwargs"]
groovy> mymethod('hello', 'world', from: 'kwargs')
arg1: hello, arg2: world, args: [], kwargs: ["from":"kwargs"]
You'll note that the last example, without positional arguments, is not possible in the current Groovy simulation from above, because a method signature is not created that supports it.