How do CharRange and LongRange differ from IntRange, and how does iterating `'a'..'z'` work under the hood?
answer
- Int/Long/Char each have Range + Progression
- CharRange iterates UTF-16 code units
- CharProgression.step is an Int
- LongRange = Long arithmetic for big bounds
- Double range = ClosedFloatingPointRange, NOT iterable
basics
~10 sCharRange spans characters like 'a' to 'z', and LongRange spans large whole numbers. They work just like IntRange but for those types, and looping over 'a'..'z' gives each letter in order.
solid answer
~30 sCharRange and LongRange mirror IntRange's design for Char and Long. `CharRange` extends `CharProgression` (which is `Iterable<Char>`) and `ClosedRange<Char>`; `LongRange` extends `LongProgression` and `ClosedRange<Long>`. `'a'..'z'` builds a CharRange with `first='a'`, `last='z'`, step 1. Iteration uses the character codes: each Char's UTF-16 code unit is incremented by the step, so it yields 'a','b',...,'z'. CharProgression's `step` is actually an `Int` (the increment over codes), while `first`/`last` are `Char`. LongRange uses `Long` arithmetic to support values beyond Int's range. You can still apply `step` and `downTo`: `'z' downTo 'a' step 2` or `0L..1_000_000_000_000L`.
code
kotlin · 10 linesval letters: CharRange = 'a'..'z'
for (c in letters step 5) print(c) // a f k p u z
val big: LongRange = 0L..3_000_000_000L
println(big.last) // 3000000000
// Double range is NOT iterable:
val d = 1.0..2.0 // ClosedFloatingPointRange<Double>
println(1.5 in d) // true (membership works)
// for (x in d) {} // compile error: not Iterablego deeper
Knows 'a'..'z' loops over letters and LongRange handles big numbers.
Explains the parallel Range/Progression pairs and that Char iteration is over character codes.
Knows CharProgression.step is Int, LongRange uses Long arithmetic, and Double ranges are not Iterable.
Reasons about UTF-16 code-unit semantics, surrogate/non-ASCII caveats, and why floating-point ranges deliberately omit iteration.
## The three closed-range type families Kotlin ships parallel families, each a closed range over a primitive: | Range type | Progression supertype | Element type | |------------|----------------------|--------------| | `IntRange` | `IntProgression` | `Int` | | `LongRange`| `LongProgression` | `Long` | | `CharRange`| `CharProgression` | `Char` | Each `*Range` extends its `*Progression` (which implements `Iterable`) **and** `ClosedRange<T>`/`OpenEndRange<T>`. ## CharRange ```kotlin val letters: CharRange = 'a'..'z' println(letters.first) // a println(letters.last) // z for (c in 'a'..'e') print(c) // abcde ``` Under the hood, a `Char` is a UTF-16 code unit (an unsigned 16-bit code). Iterating a `CharProgression` increments the **code** by the step and reinterprets it as a `Char`. A subtle detail: `CharProgression.step` is typed as `Int` (the code increment), while `first` and `last` are `Char`. So `'a'..'z' step 2` yields 'a','c','e',... with `step == 2`. Because iteration is purely numeric over code units, `'a'..'z'` only covers ASCII lowercase letters; ranges over non-contiguous alphabets behave according to the underlying code points, not linguistic order. ## LongRange `LongRange` exists so ranges can exceed `Int.MAX_VALUE`: ```kotlin val big: LongRange = 0L..3_000_000_000L println(big.last) // 3000000000 ``` Arithmetic is done in `Long`, avoiding overflow that an Int-based range would hit. Note: there is **no** `ShortRange`/`ByteRange`/`DoubleRange` progression you can iterate — `1.0..2.0` makes a `ClosedFloatingPointRange<Double>` that supports `in` but is **not** `Iterable` (you cannot for-loop it). ## step and downTo apply uniformly ```kotlin for (c in 'z' downTo 'a' step 2) print(c) // z x v t ... for (n in 10L downTo 0L step 5) print("$n ") ``` These return `CharProgression`/`LongProgression` respectively (not the `*Range` subtype), exactly like the Int case. ## Key takeaways - Char/Long ranges mirror Int's range/progression pair, just over Char/Long. - Char iteration is numeric over UTF-16 code units; `CharProgression.step` is an `Int`. - LongRange uses Long arithmetic for large bounds; Double ranges exist but are not iterable.
- Can you iterate `1.0..2.0`?No. A Double range is a ClosedFloatingPointRange<Double> that supports `in` membership but is not Iterable, so a for-loop won't compile.
- What type is CharProgression.step?Int — it's the increment applied to the Char's UTF-16 code; first and last remain Char.
saying these in an interview costs you the question
- Claiming you can for-loop a Double/Float range
- Saying CharProgression.step is a Char
- Assuming LongRange overflows like Int at large bounds
- Thinking 'a'..'z' covers accented or non-ASCII letters
- Believing there is a ByteRange/ShortRange progression to iterate