Deep copy of list should be simplified

As for today, I’ve failed to found a simple, universal solution for creating deep copies of classes that dereive from Iterable. Currently, creating a simple copy of Kotlin collection looks like this:

val newList = listOf()
for element in oldList {
    newList.add(element.copy())
}
return newList

This should be simplified, to a single method, the way that Rust / Python handles is, for example

val newList = oldList.clone()

Creating an extenstion function doesn’t seem to be possible, since .copy() method is only provided for some classes.

1 Like
val newList = oldList.map { it.copy() }

I’m aware of this, but still, a simple clone() or copy() would be much more pleasant to use

You can write your own with one line of code. The problem with a standard function is that there is no commonly agreed definition of deep. How deep? One level deep, x levels, all levels? What about lists of lists of list? What about recursive data structures, where the innermost values are equal to the outermost values?

I’m not sure I understand what exactly are you asking, how would this .copy() behave if the objects in the list don’t have a .copy() method?

There are many ways to clone objects. For instance, without even implementing the Cloneable interface, but assuming your objects are serializable, you could:

fun <T> T.clone() : T
{
    val byteArrayOutputStream=ByteArrayOutputStream()
    ObjectOutputStream(byteArrayOutputStream).use { outputStream ->
        outputStream.writeObject(this)
    }

    val bytes=byteArrayOutputStream.toByteArray()

    ObjectInputStream(ByteArrayInputStream(bytes)).use { inputStream ->
        return inputStream.readObject() as T
    }
}

Usage:

val list2 = list1.clone()
val anyOtherObject2 = anyOtherObject1.clone()

But this method does not gives the programmer the flexibility to choose how to clone, what to clone etc

But this is not an assumption that can be made by the standard library. There are many reasons why people don’t like java Object.clone. Even the documentation of it states that you can’t make any assumptions about it’s result. Not even simple statements like x.clone() == x or x.clone().getClass == x.getClass() can be assumed to always be true. All that is supposed to be guaranteed is that x.clone() !== x, which means the function is practically useless for any generic usage. Thankfully kotlin didn’t make the same mistake and removed this function form Any.

There might be a point in discussing adding a Cloneable interface to kotlin and deciding on a strict definitions what this interface should mean. Otherwise there is no way to create a deepCopy. The problem I see with this is that the best definition of Cloneable probably depends on the project and therefor can not be made by the standard library.