Transform collections with a visible data flow
filter retains matching elements, map transforms each retained element, and fold accumulates from an explicit starting value. reduce starts from the first element and therefore fails on empty collections unless you choose reduceOrNull.
data class Session(val topic: String, val minutes: Int)
fun main() {
val sessions = listOf(Session("Kotlin", 25), Session("Compose", 50))
val titles = sessions.filter { it.minutes >= 30 }.map { it.topic }
val total = sessions.fold(0) { sum, session -> sum + session.minutes }
check(titles == listOf("Compose"))
check(total == 75)
}
Each operation communicates one step. A chain that mixes mutation, logging, network calls, and transformation is harder to reason about. For summing one field, sumOf often states intent more directly.
Exercise
Calculate total minutes for a selected topic and return zero for no matches. Test empty input and several sessions with the same topic.
Check: explain why replacing fold(0) with reduce needs an explicit empty-input policy.