if you use no named arguments, the compiler will always prefer “normal” arguments over varargs, when possible
If you use named arguments, you have to pack the values for a vararg in an array, so you are effectively changing the signature to debug(input: String, data: Array<Any>), and that makes the vararg case more specific than having just an Anyargument.
What does it mean to be “more specific”? That the type is located lower in the type hierarchy?
I don’t understand the rationale behind this behaviour. Why is the second parameter treated as Array<Any> once and not both times? As I understand it, when the method with vararg parameter is compiled, the type of the last parameter will be Array<Any> no matter how it’s called.
I agree it’s a little confusing, but you really want the behavior that normal arguments are considered first, else you have problems writing code where the vararg version uses the normal one:
fun Box.add(item: Item) ...
fun Box.add(vararg items: Item) { items.foreach{ add(it) } }
On the other hand, if you use named arguments, you want that the vararg version can be called easily. If the rules were different, how would you even call the vararg version in your example? I don’t think there is a way to do this.
I think it comes do pragmatism and expectations. People from Java expect varargs to behave a certain way, but now also named arguments have to be considered, and must work somehow…
Basically, if the call with a named argument didn’t call the method with vararg parameter, then there would be no way to call it since methods with a single element parameter is preferred over the vararg one when only 1 element is supplied.
What did you mean by being “more specific” though?
If you pass an Array<String> as an argument, and one signature accepts Any and the other one accepts Array<Any>, the second one is more specific.
If you really want to know the gory details: Kotlin language specification , in particular “11.4 Choosing the most specific candidate from the overload candidate set”