How do you build a descending range and how do you change the increment? Explain `downTo` and `step`.
answer
- `downTo` to descend; `..` never counts down
- `step` must be POSITIVE (even descending)
- Direction from downTo, magnitude from step
- `last` recomputed to last reachable value
- No `..<` for descending — use downTo
basics
~10 sUse downTo to count down, like 5 downTo 1. Use step to skip values, like 0..10 step 2 for 0,2,4,6,8,10. You can combine them: 10 downTo 0 step 2.
solid answer
~40 sDescending iteration uses the infix function `downTo`: `5 downTo 1` yields 5,4,3,2,1 (inclusive, step -1). Plain `..` never counts down — `5..1` is empty. To change the increment, chain the infix `step` function with a **positive** value: `0..10 step 2` -> 0,2,4,6,8,10. `step` always takes a positive int even for descending progressions; the direction comes from `downTo`, so `10 downTo 0 step 3` -> 10,7,4,1. Both return an `IntProgression` (or `LongProgression`/`CharProgression`). The `last` value is recomputed to the largest reachable value that fits the step — e.g. `0..10 step 3` ends at 9, not 10. Passing a non-positive `step` throws `IllegalArgumentException`. There is no `..<` operator for descending; combine `downTo` with `step` instead.
code
kotlin · 5 linesprintln((10 downTo 0 step 2).toList()) // [10, 8, 6, 4, 2, 0]
println((0..10 step 3).last) // 9, not 10
try { 1..10 step -1 } catch (e: IllegalArgumentException) {
println(e.message) // Step must be positive...
}go deeper
Can write 5 downTo 1 and 0..10 step 2 and read the output.
Explains step must be positive, direction comes from downTo, and combining the two.
Knows last is recomputed to the last reachable value and that these return IntProgression; handles the IllegalArgumentException contract.
Reasons about progression internals (first/last/step normalization), Long/Char variants, and why an exclusive descending operator was intentionally omitted.
## Descending: `downTo` The `..` operator only goes **up**, so `5..1` is an *empty* range. To iterate downward, use the infix standard-library function **`downTo`**: ```kotlin for (i in 5 downTo 1) print(i) // 54321 println((5 downTo 1).toList()) // [5, 4, 3, 2, 1] ``` `downTo` is **inclusive** on both ends and uses a default step of **-1**. It returns an `IntProgression` (an arithmetic sequence start..end with a step). ## Changing the increment: `step` `step` is an infix function that sets the **magnitude** of the increment. It must be **strictly positive**, regardless of direction: ```kotlin println((0..10 step 2).toList()) // [0, 2, 4, 6, 8, 10] println((10 downTo 0 step 3).toList()) // [10, 7, 4, 1] ``` The direction (ascending/descending) is decided by `..`/`until`/`downTo`; `step` only changes the size of each jump. Calling `step` with `0` or a negative number throws: ```kotlin 0..10 step -2 // IllegalArgumentException: Step must be positive, was: -2. ``` ## How `last` is adjusted A progression stores `first`, `last`, and `step`. When you apply a `step` that doesn't divide the span evenly, Kotlin recomputes `last` to the **last value actually reachable**: ```kotlin val p = 0..10 step 3 // 0, 3, 6, 9 println(p.last) // 9 (NOT 10 — 10 is unreachable from 0 by +3) ``` This means `p.last` may differ from the bound you wrote. Membership and iteration both respect the corrected `last`. ## Combining the operators You can stack them. Precedence: `..`/`downTo`/`until` bind first, then `step`: ```kotlin 100 downTo 0 step 25 // 100, 75, 50, 25, 0 0..<10 step 3 // 0, 3, 6, 9 (half-open then stepped) ``` There is **no** `..<`-style descending operator; for an exclusive lower-bound descent, adjust the endpoint manually (e.g. `10 downTo 1` to exclude 0). ## Types `downTo` and `step` exist for `Int`, `Long`, and `Char`, returning `IntProgression`, `LongProgression`, and `CharProgression` respectively.
- Why doesn't `step` take a negative number for descending ranges?Direction is already encoded by `downTo`. `step` only sets the magnitude and is validated to be positive; a negative value throws IllegalArgumentException.
- What is `(0..10 step 3).last`?9 — the last value reachable from 0 by +3 within the bound; `last` is recomputed, not the literal 10.
- How do you make a half-open descending range?There's no `..<` for descent; adjust the endpoint, e.g. `10 downTo 1` to exclude 0.
Walking down stairs (downTo) two steps at a time (step 2) — you always step a positive number of stairs; the 'down' is the direction you face.
saying these in an interview costs you the question
- Using `5..1` and expecting it to count down
- Passing a negative value to `step`
- Assuming `(0..10 step 3).last == 10`
- Inventing a descending `..<` operator