Build transformations from smaller transformations
Composition connects one function's output to another's input. Partial application fixes some inputs while leaving the rest for a later call. Kotlin supports these patterns with ordinary function values without a dedicated composition operator.
fun <A, B, C> compose(first: (A) -> B, second: (B) -> C): (A) -> C =
{ input -> second(first(input)) }
fun main() {
val label = compose<String, String, String>({ it.trim() }, { it.uppercase() })
check(label(" Kotlin ") == "KOTLIN")
val addFive: (Int) -> Int = { value -> value + 5 }
check(addFive(3) == 8)
}
Order matters: formatting, filtering, and validation may not commute. A composition helper is useful only if it makes the sequence easier to understand than a direct function body.
Exercise
Compose trimming, blank validation, and normalization. Define whether invalid input returns null or throws, then keep that contract consistent across the composed types.
Check: demonstrate a pair of transformations whose reversed order produces different results, such as taking a prefix before or after trimming.