skip to content

What is an IntRange in Kotlin, and how does it relate to IntProgression? How do you iterate one in a for-loop?

level: juniorimportance: must knowfreq 70%

answer

  1. IntRange = inclusive [first, last], step always 1
  2. IntRange extends IntProgression
  3. Progression = first, last, step; Iterable<Int>
  4. .. is rangeTo; for (i in 1..10)
  5. Long/CharRange are the siblings

basics

~20 s

An IntRange is a span of integers from a start to an end value, like 1 to 10. You can loop over it with a for-loop, and each step it gives you the next number.

solid answer

~30 s

An IntRange represents a closed (inclusive) range of Int values defined by a start and endInclusive bound, created with the `..` operator or `rangeTo`. It is a subtype of IntProgression, which adds a `step` (default 1) and exposes `first`, `last`, and `step`. Because IntProgression implements `Iterable<Int>`, an IntRange can be used directly in a for-loop: `for (i in 1..10) { ... }`. Iteration yields first, first+step, ... up to and including last. IntRange also implements `ClosedRange<Int>` (and `OpenEndRange<Int>`) so it supports `contains`/`in`. Sibling LongRange and CharRange behave the same for Long and Char.

code

kotlin · 11 lines
kotlin
val range: IntRange = 1..10
println(range.first)  // 1
println(range.last)   // 10
println(range.step)   // 1

// IntRange IS an IntProgression
val p: IntProgression = range

for (i in 1..5) print(i)  // 12345

println((5..1).isEmpty()) // true: start > end

go deeper

for a junior

Knows .. makes an inclusive range and that you loop with for (i in 1..10).

for a middle

Explains IntRange extends IntProgression and that first/last/step exist with step defaulting to 1.

for a senior

Notes IntRange also implements ClosedRange/OpenEndRange, that the loop is often allocation-free, and that 5..1 is empty.

for a principal

Can reason about the dual interface inheritance (progression Iterable + ClosedRange membership) and the compiler loop-lowering optimization implications.

## What an IntRange is An `IntRange` is a Kotlin standard-library type representing a **closed (inclusive) interval** of `Int` values: it has a start and an `endInclusive`, both included. You create one most often with the `..` range operator, which is sugar for the `rangeTo` function: ```kotlin val r: IntRange = 1..10 // 1, 2, ..., 10 (both ends included) println(r.first) // 1 println(r.last) // 10 println(r.step) // 1 ``` ## Relationship to IntProgression The class hierarchy is the key idea: - `IntProgression` is an **arithmetic progression** of `Int`s defined by three numbers: `first`, `last`, and `step` (a non-zero step). It implements `Iterable<Int>`. - `IntRange` is a **subclass** of `IntProgression` whose `step` is always `1`. It *also* implements `ClosedRange<Int>` and `OpenEndRange<Int>`, which is what gives it `contains`/membership semantics. So every `IntRange` is an `IntProgression`, but not every progression is a range. A `2..10 step 2` produces an `IntProgression` (step 2), not an `IntRange`. ## Iterating in a for-loop Because `IntProgression` implements `Iterable<Int>`, you can put a range directly after `in`: ```kotlin for (i in 1..5) print(i) // 12345 ``` The compiler frequently **optimizes** `for (i in a..b)` into a plain counting loop with no allocation or iterator object, but semantically it iterates `first`, `first + step`, ... while the value has not passed `last`. ## Other range types - `LongRange` / `LongProgression` — same shape for `Long`. - `CharRange` / `CharProgression` — same shape for `Char`, e.g. `'a'..'z'`. ## Empty ranges If the start is greater than the end (with a positive step), the range is **empty**: `(5..1).isEmpty()` is `true`, and the for-loop body never runs. `IntRange.EMPTY` is a canonical empty instance. ## Key takeaways - `..` creates an inclusive `IntRange`. - `IntRange` extends `IntProgression`; progressions carry `first`, `last`, `step`. - Progressions are `Iterable`, so they work in for-loops, often without allocation.

  • Is 1..10 inclusive or exclusive of 10?
    Inclusive — IntRange is a closed range, so both 1 and 10 are produced. Use 1 until 10 (or 1..<10) for an exclusive upper bound.
  • What's the type of 2..10 step 2?
    IntProgression, not IntRange, because the step is no longer 1.

A progression is like setting a metronome (start, end, tick interval); an IntRange is that metronome locked to a tick of 1.

saying these in an interview costs you the question

  • Saying IntRange is exclusive of the upper bound
  • Claiming IntRange and IntProgression are unrelated types
  • Thinking a for-loop over a range always allocates an iterator object
  • Confusing `..` (rangeTo) with `until` semantics
  • Believing 5..1 throws instead of being empty

context