05: Control Flow
Audience: All Time: 90 minutes Prerequisites: 01-04 You'll learn: if/else, match, for loops, while loops, guards, break/continue
The Big Picture
Control flow directs which code runs based on conditions. Instead of executing every line in order, you: - Skip code if a condition isn't met (if) - Repeat code until done (for, while) - Branch based on many options (match)
If / Else
Basic If
// file: 05_if.zbr
// teaches: conditional execution // chapter: 05-Control-Flow
class Main shared def main var age as int = 18
if age >= 18 print "You can vote"
If / Else
// file: 05_if_else.zbr
// teaches: if-else branching // chapter: 05-Control-Flow
class Main shared def main var score as int = 75
if score >= 90 print "A" elif score >= 80 print "B" elif score >= 70 print "C" else print "F"
Breakdown: - if condition — Execute if true - elif condition — Else-if (try next condition) - else — Default case (if all above are false)
Multiple Conditions
// file: 05_conditions.zbr
// teaches: boolean logic // chapter: 05-Control-Flow
class Main shared def main var age as int = 25 var has_license as bool = true
if age >= 18 and has_license print "Can drive"
if age < 16 or not has_license print "Cannot drive"
Operators: - and — Both must be true - or — At least one must be true - not — Flip the value
Match (Pattern Matching)
Match is more powerful than if/else. It handles many cases elegantly.
Simple Match
// file: 05_match.zbr
// teaches: pattern matching // chapter: 05-Control-Flow
class Main shared def main var color as str = "red"
branch color on "red" print "Stop" on "yellow" print "Caution" on "green" print "Go" else print "Unknown"
Match With Types
// file: 05_match_type.zbr
// teaches: type-based matching // chapter: 05-Control-Flow
class Animal pass
class Dog inherits Animal def bark print "Woof!"
class Cat inherits Animal def meow print "Meow!"
class Main shared def main var pet as Animal = Dog()
if pet implements Dog var d = pet to Dog d.bark()
If you know Python
<h1>Python</h1>
match color: case "red": print("Stop") case "green": print("Go")
<h1>Zebra</h1> branch color on "red" print "Stop" on "green" print "Go"
Loops
For Loop (Iteration)
// file: 05_for.zbr
// teaches: for loop iteration // chapter: 05-Control-Flow
class Main shared def main var fruits as List(str) = List() fruits.add("apple") fruits.add("banana") fruits.add("cherry")
for fruit in fruits print fruit
// With index (if supported) var i = 0 while i < fruits.count() print "Item ${i}: ${fruits.at(i)}" i = i + 1
While Loop (Condition-Based)
// file: 05_while.zbr
// teaches: while loop // chapter: 05-Control-Flow
class Main shared def main var count as int = 0
while count < 5 print "Count: ${count}" count = count + 1
print "Done!"
Break and Continue
// file: 05_break_continue.zbr
// teaches: loop control // chapter: 05-Control-Flow
class Main shared def main // Break: exit loop early var i = 0 while true if i == 5 break print i i = i + 1
// Continue: skip to next iteration for num in 1..10 if num % 2 == 0 continue print num // Prints odd numbers only
Guards
Guards are conditions that must be true for code to run.
// file: 05_guards.zbr
// teaches: guard conditions // chapter: 05-Control-Flow
class Main shared def process(name as str) # Early return if invalid if name.len == 0 return if name.len > 100 return
# Process only if valid print "Processing: ${name}"
def main process("") // Returns early process("Alice") // Processes process("x" * 200) // Returns early
Real World: Data Validation
// file: 05_validation.zbr
// teaches: practical control flow // chapter: 05-Control-Flow
class Email var address as str
class Validator shared def validate_email(email as str) as bool # Check not empty if email.len == 0 return false
# Check has @ if not email.contains("@") return false
# Check has domain var parts = email.split("@") if parts.count() != 2 return false
var domain = parts.at(1) if not domain.contains(".") return false
return true
class Main shared def main var emails as List(str) = List() emails.add("alice@example.com") emails.add("invalid.email") emails.add("bob@domain.co")
for email in emails if Validator.validate_email(email) print "Valid: ${email}" else print "Invalid: ${email}"
Common Patterns
Early Return
def process_order(order_id as int) as bool
var order = fetch_order(order_id)
if order == nil return false
if order.total == 0 return false
if not order.has_items return false
# Do the real processing charge_card(order) ship_items(order) return true
Nested Conditions
for user in users
if user.is_active for order in user.orders if order.status == "pending" process_order(order)
Else-If Chain
if age < 13
category = "child" elif age < 18 category = "teen" elif age < 65 category = "adult" else category = "senior"
Common Mistakes
> ❌ Mistake: Forgetting the condition > >
> if age >= 18 # Missing condition or wrong structure > print "Adult" > print "Extra" # Both print regardless > > > ✅ Better: > > if age >= 18 > print "Adult" > else > print "Minor" >
> ❌ Mistake: Unreachable code > >
> if x > 0 > return true > else > return false > return false # ❌ Never reached > > > ✅ Better: > > if x > 0 > return true > return false >
> ❌ Mistake: Mutating collection while iterating > >
> for fruit in fruits > if fruit == "apple" > fruits.remove(fruit) # ❌ Unsafe > > > ✅ Better: > > var to_remove as List(str) = List() > for fruit in fruits > if fruit == "apple" > to_remove.add(fruit) > for fruit in to_remove > fruits.remove(fruit) >
Exercises
Exercise 1: Grade Calculator
Write a function that converts numeric scores to letter grades:
Solution
class Grader
shared def grade_to_letter(score as int) as str if score >= 90 return "A" elif score >= 80 return "B" elif score >= 70 return "C" elif score >= 60 return "D" else return "F"
class Main shared def main var scores as List(int) = List() scores.add(95) scores.add(75) scores.add(88) scores.add(62)
for score in scores var grade = Grader.grade_to_letter(score) print "${score} = ${grade}"
Exercise 2: Find Maximum
Iterate through a list and find the maximum value:
Solution
class Finder
shared def find_max(nums as List(int)) as int if nums.count() == 0 return 0
var max_val = nums.at(0) for num in nums if num > max_val max_val = num return max_val
class Main shared def main var nums as List(int) = List() nums.add(10) nums.add(45) nums.add(23) nums.add(89) nums.add(34)
var max = Finder.find_max(nums) print "Max: ${max}" // 89
Exercise 3: Filter With Control Flow
Count elements matching a condition:
Solution
class Counter
shared def count_evens(nums as List(int)) as int var count = 0 for num in nums if num % 2 == 0 count = count + 1 return count
class Main shared def main var nums as List(int) = List() nums.add(1) nums.add(2) nums.add(3) nums.add(4) nums.add(5) nums.add(6)
var even_count = Counter.count_evens(nums) print "Even numbers: ${even_count}" // 3
Next Steps
- → 06-Strings-and-Unicode — Text manipulation - → 05-Control-Flow — Combine control flow with strings - 🏋️ Project-1-CLI-Tool — Use loops and conditions extensively
Key Takeaways
- if/else handles simple binary choices - match (branch) is better for many cases - for loops iterate over collections - while loops repeat based on conditions - break exits loops, continue skips iterations - Early return makes functions clearer - Guard clauses prevent "arrow code" (deeply nested if statements)
Next: Head to 06-Strings-and-Unicode to work with text.