Make boundaries visible
1..5 includes both endpoints. 1 until 5 excludes five. A progression adds a step or direction; downTo counts downward, while step takes a positive step size.
fun main() {
println((1..5).toList())
println((1 until 5).toList())
println((5 downTo 1 step 2).toList())
val topics = listOf("A", "B")
for (i in topics.indices) println(topics[i])
}
The lists are [1, 2, 3, 4, 5], [1, 2, 3, 4], and [5, 3, 1]. indices expresses valid list indexes. 0..topics.size is wrong because the final included value is past the last index, and an empty collection makes this especially easy to miss.
A numeric range normally describes bounds without allocating a list of all elements. Calling toList() materializes those elements, which matters for large ranges.
Exercise
Write a function returning every third positive integer below a limit. Test limits 0, 1, 4, and 10. Decide whether the sequence begins at one or three and document that contract.
Check: if it begins at three, limit ten yields [3, 6, 9], and limit one yields an empty list.