spand
11/23/2021, 9:11 AMflatten()
with a transform
been considered ? Seems like an obvious addition which would enable us to skip a list allocation (we have a bunch of flatten().map { it.idOfEntity }
) not to mention it being a bit simpler: flatten { it.idOfEntity }
A difference with normal flatten
would be that it no longer calls addAll()
which allows it to possibly skip a few grows but given that it can skip an entire copy on the next map
in our case it seems like it should win out. Maybe that would be a reason for keeping both as overloads and not add transform with default parameter.
Example implementation:
public inline fun <T, R> Iterable<Iterable<T>>.flatten(transform: (T) -> R): List<R> {
val result = ArrayList<R>()
for (elementIterable in this) {
for (element in elementIterable) {
result.add(transform(element))
}
}
return result
}
ephemient
11/23/2021, 10:24 AMinline fun <T, R> Iterable<T>.transform(transform: MutableList<R>.(T) -> Unit): List<R> = buildList {
for (it in this@transform) {
transform(this, it)
}
}
to align with fun Flow<T>.transform(transform: suspend FlowCollector<R>.(T) -> Unit): Flow<R>
, you could use
.transform { it.mapTo(this) { it.idOfEntity } }
ephemient
11/23/2021, 12:22 PMspand
11/23/2021, 1:29 PM.transform { it.mapTo(this) { it.idOfEntity } }
instead of ie. flatten().map { it.idOfEntity }
would really stand out. Its obviously not fair to compare such a flexible function like your transform
but the mental load is quite large versus mine which imo fits quite well in with the rest of the collection mapping functions.ephemient
11/23/2021, 4:49 PMSequence<Sequence<T>>.flatten(transform: (T) -> R)
or a Flow<Flow<T>>.flatten(transform: (T) -> R)
, while there is a Flow<T>.transform(...)
, so I figure that interface is already well known. flatten+map
looks like an easy shortcut, but there's so many other things that could be more efficient if chained from flatten
that I'm not sure this one is special enough. rather than adding flat versions of .map/Indexed/NotNull/To
, .min/max/Of/With/OrNull
, .any/all/none
, .associate/By/With/To
, etc., using .asSequence().flatten()
first has some different tradeoffs but doesn't take up any more API spacespand
11/24/2021, 7:25 AMflatten()
in the first place when flatMap { it }
is almost as short and probably identical in performance from what I can glean from the bytecode.
Thanks for the talkspand
11/24/2021, 7:56 AMephemient
11/24/2021, 5:46 PMflatMap
isn't strictly necessary, but it is common enough. obviously YMMV, but looking through my code, I do see a few places where .flattenMapNotNull()
could be used, quite a lot of places where .transform()
could be used, but no occurrences that could be written with .flatten(transform)
. fine to file a feature request, but personally I don't find it convincing.