Extract repeated transformations into named operations
A collection extension is useful when it expresses a recurring domain operation. Keep its name specific, define empty-input behavior, and avoid hiding mutation behind an innocent-looking query.
fun Iterable<Int>.positiveAverageOrNull(): Double? {
var sum = 0L
var count = 0L
for (value in this) {
if (value > 0) {
sum += value
count++
}
}
return if (count == 0L) null else sum.toDouble() / count
}
This consumes the iterable once without an intermediate filtered list. Long reduces overflow risk for ordinary datasets, but enormous totals still need explicit bounds or another numeric representation. An iterable need not support indexing or repeated traversal.
Exercise
Write sumWithin(range) for integers using one pass. Test an empty collection, no matching elements, and matching boundary values.
Check: document whether the function mutates its receiver and whether the endpoints of the range are included. Compare clarity with built-in combinations before adding a custom extension to a shared library.