Nir
07/28/2020, 8:14 PMdata class Foo(val bar: List<T>)
Despite the use of both val and List (as opposed to MutableList), it's still pretty easy to mutate data out from underneath Foo. I was curious how many people had felt the need to have some kind of true immutable list type, to prevent this scenario? One pleasant surprise in Kotlin was that I was able to implement something reasonable in just a handful of lines. Even just:
class ImmutableList<T> private constructor(val data: List<T>) : List<T> by data {
constructor(x: Sequence<T>) : this(x.toList())
constructor(x: Iterable<T>) : this(x.toList())
}
operator fun<T> ImmutableList<T>.plus(x: Sequence<T>) = (data.asSequence() + x).toImmutableList()
operator fun<T> ImmutableList<T>.plus(x: Iterable<T>) = (data + x).toImmutableList()
operator fun<T> ImmutableList<T>.plus(x: T) = plus(sequenceOf(x))
fun <T> immutableListOf(vararg elements: T) = elements.asIterable().toImmutableList()
fun <T> Sequence<T>.toImmutableList() = ImmutableList<T>(this)
fun <T> Iterable<T>.toImmutableList() = ImmutableList<T>(this)
Is already pretty usable (thanks mostly to delegation). And now we can go back to our previous example:
data class Foo(val bar: ImmutableList<T>)
This is actually conditionally immutable depending on the T (say it's an Integer or String).
I'm curious if many people are using things similar to this? Or are people just living with the possibility of unexpected mutations in Foo, finding it not too big of a problem?Zach Klippenstein (he/him) [MOD]
07/28/2020, 8:16 PMNir
07/28/2020, 8:22 PMNir
07/28/2020, 8:24 PMNir
07/28/2020, 8:25 PMNir
07/28/2020, 8:27 PMBig Chungus
07/28/2020, 8:30 PMNir
07/28/2020, 8:31 PMval x = mutableListOf(1,2,3)
val f = Foo(x)
x.add(4)
Big Chungus
07/28/2020, 8:42 PMMatteo Mirk
08/14/2020, 10:39 AMNir
08/14/2020, 2:07 PMNir
08/14/2020, 2:07 PMNir
08/14/2020, 2:09 PMImmutableList
class or something like it, then you don't need the defensive copying. Also, I provide a version of map
that returns an ImmutableList instead of List. If you think about it map
is returning a List that nobody has a mutable reference to, so it's already "safe" shy of downcasting. Just need to reflect that in the type system.Matteo Mirk
08/14/2020, 2:31 PMList
instances. If data comes from an external client I can just defensive copy unless we’re dealing with thousands or million elements, or require an ImmutableList if the need arises.Nir
08/14/2020, 2:34 PM