I swear I have long covid and brain fog or somethi...
# getting-started
I swear I have long covid and brain fog or something. Is there an idiomatic way in Kotlin to
while supplying the map-like operation with a list of functions (or vararg) to apply to each element, rather than a single transformation? basically
collection.mapAll(transformers: List<(T) -> R>)
sequence.mapAll(transformers: List<(T) -> T>)
I want to supply a list of transformers so I don’t have to do something like:
Copy code
would be:
Copy code
I don't think there is any built-in stdlib function to do that directly. But you could implement your own. Note that
List<(T) -> R>
cannot work in general, though, because you would need each function's output type to be the same (or a subtype) of the next function's input type.
🤔 if you are mapping, you are changing the types, so I don't see this list of transformers working (how would the compiler ensure the types?)
not handle this case without having to make multiple iterations? 🤔
If I'm not mistaken there is a "common" rule: if you have more than 2 transform operators you'd better use a sequence.
I may be approaching the problem incorrectly. The input type in each transformer is the the same as the output. It’s basically like a reducer, but I keep each element. Each function has a responsibility to calculate some specific business rule and applies its value to an accumulator.
I am using a sequence.
I should change the “collection” to “sequence” in my example.
⬆️ 1
extension functions to the rescue :)
Ok. I thought there might be a way to just simply apply a list of functions with an argument, like a chain, where the output is the input of the next in the list.
If the types are all the same, one way to roll your own is the following:
Copy code
fun <T> Sequence<T>.map(transforms: List<(T) -> T>): Sequence<T> =
    transforms.fold(this) { s, t -> s.map(t) }
See: https://pl.kotl.in/clSuDg4m0
👌 1
hah. thanks.
Note that this
is not operating on the sequence, but on the list of transformations, so it builds a new sequence by repeatedly applying
with each transform. The initial value for the fold is the initial sequence.
hmmm. I’ll have to think about that one.
Thanks all for info. At least I know there isn’t a “native” way to apply this. Again, I am pretty sure I might be doing something “wrong”, but I am just working on a PoC for extracting and reporting on data from an external system in a concise and extensible way to supply new functionality without modifying the execution code.
And I wasn’t kidding about the brain fog. It’s like I used to be able to play chess, think a few moves ahead, and now I can only imagine one or two. It’s odd. Hah. All the caffeine in the world doesn’t help.
🥲 2
BTW, I also fixed the signature as it was wrong: It should have always been:
(T) -> T
(T) -> R
(for my example)
Another way:
Copy code
sequence.map {
This also works just as well with collections, as it transforms it element-by-element.
I need to pass a collection of functions. The list is unknown until it’s executed.
you could fold over the transforms while mapping each individual element,
Copy code
fun <T> Sequence<T>.map(transforms: Iterable<(T) -> T>): Sequence<T> = map {
    transforms.fold(it) { s, t -> s.map(t) }