Control Flow in Kotlin
Master conditionals, when expressions, and loops in Kotlin with practical Docker-ready examples covering if/else, ranges, and loop control
Control flow is how a program decides what to do next: which branch to take, which block to repeat, and when to stop. Kotlin keeps the familiar if, for, and while from Java but reshapes them around one core idea—control structures are expressions, not just statements. An if can produce a value, a when can replace a sprawling switch, and ranges make loops read like plain English.
Because Kotlin is multi-paradigm (object-oriented and functional), it gives you both worlds: imperative loops when you want them, and expression-oriented branching that fits a functional style. There’s no ternary ?: operator in Kotlin—you don’t need one, because if already returns a value. Likewise, when is far more powerful than a C-style switch, supporting ranges, type checks, and arbitrary conditions.
In this tutorial you’ll learn how Kotlin handles conditionals with if/else, the versatile when expression, the full family of loops (for, while, do/while), range expressions, and loop control with break, continue, and labels. Every example is self-contained and runnable in Docker.
Conditionals: if/else as an Expression
In Kotlin, if/else works as both a statement and an expression. When used as an expression, the value of the chosen branch becomes the result—the last line of a block is its value.
Create a file named Conditionals.kt:
| |
When if is used as an expression (assigned to a variable), the else branch is required—the compiler must know every path produces a value.
The when Expression
when is Kotlin’s powerful replacement for the switch statement. It can match exact values, ranges, multiple values per branch, or—when used with no argument—act as a clean if/else-if chain. It also performs smart casts when checking types.
Create a file named When.kt:
| |
Notice the branches: in 4..5 matches a range, 6, 7 matches either value, and is Int checks a type while smart-casting item so you can call item * 2 directly.
Loops: for, while, and do/while
Kotlin’s for loop iterates over anything that provides an iterator—most commonly ranges and collections. Ranges (1..5, 10 downTo 0, 0 until 4) make intent clear, and withIndex() gives you both position and value.
Create a file named Loops.kt:
| |
Ranges are first-class objects: 1..5 is an IntRange, and downTo, until, and step are infix functions that build new ranges. This is why loops read so naturally.
Loop Control: break, continue, and Labels
continue skips to the next iteration and break exits the loop entirely. For nested loops, Kotlin lets you tag a loop with a label (outer@) and break or continue that specific loop with break@outer.
Create a file named LoopControl.kt:
| |
Without the label, break would only exit the inner loop. The outer@ label lets break@outer jump out of both loops at once—handy when a nested search finds what it needs.
Running with Docker
The Zenika Kotlin image compiles each example to a runnable JAR and executes it. Compile any of the four files by swapping the .kt filename.
| |
Expected Output
Running Conditionals.kt:
It's mild outside
Grade: B
b is larger
Max: 12
Running When.kt:
Day 3 is Wednesday
42 is small
Int doubled is 84
String of length 5
Double rounded is 3
Something else
Running Loops.kt:
Countup: 1 2 3 4 5
Countdown: 10 8 6 4 2 0
Indices: 0 1 2 3
0: apple
1: banana
2: cherry
T-minus 3
T-minus 2
T-minus 1
Liftoff!
Attempt 1
Attempt 2
Running LoopControl.kt:
Odd numbers: 1 3 5 7 9
Until 5: 1 2 3 4 5
Pairs: (1,2) (1,3) (2,1)
Key Concepts
ifis an expression — It returns a value, so Kotlin has no ternary operator. The last expression in a branch block is its result.whenreplacesswitch— It matches values, ranges (in 4..5), multiple options (6, 7), and types (is Int) with automatic smart casts.- Argument-less
when— Omitting the subject turnswheninto a clean if/else-if chain where each branch holds a boolean condition. - Ranges power loops —
1..5(inclusive),0 until 4(half-open),10 downTo 0(descending), andstep 2compose to express iteration clearly. withIndex()— Destructure(index, value)directly in aforloop instead of managing a counter manually.do/while— Runs its body at least once before testing the condition, unlike a plainwhile.- Labels for nested loops — Tag a loop with
label@and usebreak@labelorcontinue@labelto control the outer loop from inside a nested one. - Exhaustiveness — When
iforwhenis used as an expression, anelsebranch is required so every path yields a value.
Comments
Loading comments...
Leave a Comment