If you want a list or map that is expected to be i...
# getting-started
j
If you want a list or map that is expected to be immutable, which one of the solution will you use? 1. Accepts `List<T>`/`Map<K, V>` and let the caller ensures that it is immutable. 2. Accepts `List<T>`/`Map<K, V>` and use the `.toList`/`toMap` version. 3. Use the `ImmutableList`/`ImmutableMap` of
kotlinx.collections.immutable
. 4. Others. State in the comment.
1️⃣ 3
m
I'd choose 1 in general. The other versions only in situations like concurrency
1
k
If you can consider kotlinx.collections.immutable mature enough (at v0.3.5), then using them as function parameter types is a good way of documenting to the caller that this function requires that the collections are not modified at any time during the running of this function (e.g. either in a separate thread or in a callback). Otherwise, I would choose between 1 and 2 depending on various factors. If performance is paramount, or if the collections are very large, I would go with 1 (and document that the collections must not be modified). Otherwise, I would do 2, i.e. take a snapshot (and also document that).
m
I don't particularily agree with option 2. Either you're not strict about what happens under the hood but only care about the typing of the map being immutable like in option 1, or you HAVE to be ABSOLUTELY be sure that whatever it is that you got is immutable. Which is option 3. Making the caller responsible for the typing seems paramount to the whole ordeal. Option 2 is making the function call non-strict but than stricting it yourself. But that can mean that whoever calls the function could already have made it strict, meaning you reiterate over the list for no gain.
2
j
Also option 2 is not really much safer than option 1 with respect to concurrent mutation. Calling
toList
could break if someone modifies the underlying list while you're creating the copy. The drawback of making a full copy, depending on the size, is also a downer. 99% of the time, I don't think you need anything more than
List
or
Map
interfaces, especially if callers are in your own code base. It would be very weird for someone to concurrently modify a list when calling a function on that list, so I don't expect that to be a real problem in practice
s
@Joffrey It would be very weird for someone to concurrently modify a list when calling a function on that list, so I don’t expect that to be a real problem in practice I could think of a case (and I don’t think that it is that rare). An observable (no matter what kind) that modifies the list and at the exact time when you use the list for something else
j
A shared mutable state is usually to be avoided, it's better to use immutable messages in a lot of cases. When going down the shared mutable state path, it's necessary to use a thread safe mutable collection, and to limit visibility and access to that state, so I still would find it inappropriate to call a function you don't own on that mutable shared collection. Nevertheless, I agree it's hard to speak too generally about this. There may be cases where it happens.