Just noticed - there's no `List<T>.take(n: I...
# stdlib
r
Just noticed - there's no
List<T>.take(n: Int): List<T>
only
Iterable<T>.take(n: Int): List<T>
which constructs a new ArrayList and copies elements in. Wouldn't this be more efficient on a List, as it could just return a view?
Copy code
fun List<T>.take(n: Int): List<T> = subList(0, n)
(And of course the same for
drop
)
j
that would make it susceptible to changes in the backing list which i suspect would surprise people
☝️ 2
r
I wish Kotlin had made the default implementation of Lists immutable
e
wouldn't help unless you forbid calling that function on mutable lists, which requires a different type hierarchy
r
Yes, I was imagining an
ImmutableList<T> : List<T>
interface as a parallel to
MutableList
c
It's a times like these I wonder if having
.take
be an extension function was a good idea. If it were a regular interface method with default implementation, immutable list implementations could have overriden it to provide a subList-based implementation when it's safe
e
kotlin collections intentionally reuse java collections, so adding new member functions is not possible
kotlinx.immutable takes the approach of providing its own extension functions, which will be used if imported. although it only has
plus
and
minus
currently, no reason
take
etc. couldn't use the same pattern. does have the downside of being difficult to tell what is happening locally though
c
“which will be used if imported” ← except if you use polymorphism, which you likely do
i
An additional consideration is that if
take
was implemented as
subList
(given that the
take
contract is respected, for example, by doing so only for immutable lists), it could lead to retaining more objects from garbage collection than necessary. Suppose you have a large list, but only temporary, and you want to take and store for a long period a list of only several first elements from it. If you use
take
for that, and
take
is implemented as a view, it would retain the entire large list in memory when only several elements of it are needed.
c
And, indeed, I've seen multiple people complaining here that
String.substring
retains the original string 🙄
j
They changed that in Java 7
i
AFAIK
substring
no longer does that.
c
Really? Damn.
e
on a similar note, C++11 also ended up forbidding implementations from sharing backing buffers between strings, justified by https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2668.htm (although the situation there was a bit different due to mutable strings)