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.