Scalability Issue: Spread operator with collections

It looks like there’s a scalability issue when passing the values of a collection to a function that accepts variable arguments:

val ids: List<String> = loadIds()
processIds(*ids.toArray())

// located somewhere else:
fun processIds(vararg ids: String)

This results in a new array being created with a copy of the list elements (by calling toArray) and then a second copy is made since I need to use the spread operator on the first copy.

The problem is that I’m dealing with 2 APIs, one which returns a list (as is common in Kotlin) and another which is defined as accepting variable arguments. Since I don’t control these APIs, I can’t modify the signatures so I don’t see any way around the double copy.

Perhaps the compiler could detect this pattern. Alternatively, it would be nice if we could use the spread operator directly on the list and the compiler would do the right thing. Lastly, another option would be to allow the less-safe Java-way of passing an array directly (perhaps with an annotation).

4 Likes

I think you should create an issue about this here: https://youtrack.jetbrains.com/oauth?state=%2Fissues%2FKT
Don’t think there will be any argument against your idea of improving the performance of this.

1 Like

@Wasabi375 Thanks, I created this issue for anyone that wants to chime in on it:
https://youtrack.jetbrains.com/issue/KT-25350

I found a workaround. Create a utility method in Java and call this from Kotlin:

public static void passArrayAsVarargs(@Nonnull String[] ids) {
    processIds(ids); //processIds accepts variable arguments
}

But it feels dirty creating a Java utility method to work around this scalability issue.