Control Flow

Master Topaz control flow structures. Learn how to effectively control program execution flow through conditionals, loops, pattern matching, and guard conditions.

Control flow determines the order in which your program executes. Topaz provides powerful and expressive control flow structures. 🎯

🔀 Conditional Statements

if Statements

let age = 25
let score = 85

// Basic if statement
if age >= 18 {
    print("You are an adult")
}

// if-else statement
if score >= 90 {
    print("Grade A")
} else {
    print("More effort needed")
}

// if-else if chain
if score >= 90 {
    print("Grade A - Excellent")
} else if score >= 80 {
    print("Grade B - Good")
} else if score >= 70 {
    print("Grade C - Average")
} else {
    print("Retake required")
}

// Compound conditions
let username = "TopazDev"
let attempts = 3

if username.length() > 0 && attempts < 5 {
    print("You can attempt to login")
}

Conditional Expressions

// Use if as an expression instead of ?: (not in v3)
let adultStatus = if age >= 18 { "adult" } else { "minor" }
let passStatus = if score >= 60 { "pass" } else { "fail" }

// Nested conditions
let grade = if score >= 90 { "A" }
    else if score >= 80 { "B" }
    else if score >= 70 { "C" }
    else { "F" }

// Conditional value
let discount = if memberLevel == "VIP" { 0.2 }
    else if memberLevel == "Gold" { 0.1 }
    else { 0.05 }

print("Age: {age}, Status: {adultStatus}")
print("Score: {score}, Grade: {grade}")

if as Expression

// Using if as an expression
let message = if time < 12 {
    "Good morning!"
} else if time < 18 {
    "Good afternoon!"
} else {
    "Good evening!"
}

// Complex conditional calculation
let shippingCost = if orderAmount >= 50000 {
    0
} else if distance <= 10 {
    3000
} else {
    5000
}

print(message)
print("Shipping cost: ${shippingCost}")

🔄 Loops

for Loops

// Range-based for loop
for i in 0..5 {
    print("Iteration {i}")
}

// Inclusive range
for i in 1..=10 {
    print("Number: {i}")
}

// Array iteration
let fruits = ["apple", "banana", "orange", "grape"]
for fruit in fruits {
    print("Fruit: {fruit}")
}

// Iterate with index and value
for (index, fruit) in fruits.enumerate() {
    print("{index}: {fruit}")
}

// Object key-value iteration
let userInfo = {
    name: "TopazDev",
    age: 25,
    job: "developer"
}

for (key, value) in userInfo {
    print("{key}: {value}")
}

// Step iteration
for i in (0..20).step(2) {
    print("Even: {i}")
}

while Loops

// Basic while loop
let mut counter = 0
while counter < 5 {
    print("Counter: {counter}")
    counter += 1
}

// Conditional while loop
let mut input = ""
while input != "quit" {
    input = input("Enter command (type 'quit' to exit): ")
    if input != "quit" {
        print("Received command: {input}")
    }
}

// Infinite loop (with break)
let mut attempts = 0
while true {
    attempts += 1
    let success = Math.random() > 0.8
    
    if success {
        print("Success! After {attempts} attempts")
        break
    }
    
    if attempts >= 10 {
        print("Maximum attempts exceeded")
        break
    }
}

Loop Control

// break and continue
for i in 1..=20 {
    if i % 3 == 0 && i % 5 == 0 {
        print("{i}: FizzBuzz")
        continue
    }
    
    if i % 3 == 0 {
        print("{i}: Fizz")
        continue
    }
    
    if i % 5 == 0 {
        print("{i}: Buzz")
        continue
    }
    
    if i > 15 {
        print("Exceeded 15, stopping")
        break
    }
    
    print("{i}")
}

// Labeled loops
outer: for i in 1..=3 {
    for j in 1..=3 {
        if i * j > 6 {
            print("Product exceeds 6, breaking outer loop")
            break outer
        }
        print("{i} × {j} = {i * j}")
    }
}

🎭 Pattern Matching (match)

Basic match Statement

let dayOfWeek = "Monday"

match dayOfWeek {
    case "Monday" => print("Start of the week!")
    case "Friday" => print("TGIF!")
    case "Saturday" | "Sunday" => print("Weekend!")
    case _ => print("Regular day")
}

// match returning a value
let workType = match dayOfWeek {
    case "Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday" => "workday"
    case "Saturday" | "Sunday" => "weekend"
    case _ => "unknown"
}

print("Today is a {workType}")

Number Pattern Matching

let score = 87

let grade = match score {
    case 90..=100 => "A"
    case 80..=89 => "B"
    case 70..=79 => "C"
    case 60..=69 => "D"
    case _ => "F"
}

// Using guard conditions
let evaluation = match score {
    case x if x >= 95 => "Perfect score!"
    case x if x >= 90 => "Excellent performance"
    case x if x >= 80 => "Good result"
    case x if x >= 70 => "Average level"
    case x if x >= 60 => "Pass"
    case _ => "Retake required"
}

print("Score: {score}, Grade: {grade}, Evaluation: {evaluation}")

Struct/Object Pattern Matching

let user = {
    name: "TopazDev",
    age: 25,
    job: "developer",
    location: "Seoul"
}

// Destructuring match
match user {
    case { name: "TopazDev", age, job: "developer" } => {
        print("Topaz developer, age: {age}")
    }
    case { age: userAge, location: "Seoul" } if userAge < 30 => {
        print("Young user in Seoul")
    }
    case { job: "developer", location } => {
        print("Developer in {location}")
    }
    case _ => {
        print("Regular user")
    }
}

// Nested object matching
let order = {
    customer: { name: "TopazUser", vip: true },
    items: ["laptop", "mouse"],
    total: 1500000
}

match order {
    case { customer: { vip: true }, total: amount } if amount > 1000000 => {
        print("VIP customer large order: ${amount}")
    }
    case { customer: { name }, items } if items.length() > 1 => {
        print("{name}'s multi-item order")
    }
    case _ => {
        print("Regular order")
    }
}

Array Pattern Matching

let numbers = [1, 2, 3, 4, 5]

match numbers {
    case [] => print("Empty array")
    case [first] => print("Single element: {first}")
    case [first, second] => print("Two elements: {first}, {second}")
    case [first, ...rest] => {
        print("First: {first}, Rest: {rest}")
    }
}

// Specific pattern matching
let scoreList = [95, 87, 92]

match scoreList {
    case [100, ...] => print("Starts with perfect score!")
    case [..., 100] => print("Ends with perfect score!")
    case [a, b, c] if a > 90 && b > 90 && c > 90 => print("All scores above 90!")
    case scores if scores.all(x => x >= 80) => print("All scores above 80")
    case _ => print("Regular score distribution")
}

Enum Pattern Matching

enum Status {
    Pending,
    Processing(progress: int),
    Complete(result: string),
    Err(message: string)
}

let currentStatus = Status.Processing(progress: 75)

match currentStatus {
    case Status.Pending => print("Waiting...")
    case Status.Processing(progress: progress) => {
        print("Processing: {progress}%")
        if progress > 50 {
            print("More than halfway done")
        }
    }
    case Status.Complete(result: result) => print("Complete: {result}")
    case Status.Err(message: error) => print("Error occurred: {error}")
}

// Option type matching
let optionalValue: Option<string> = Some("Topaz")

match optionalValue {
    case Some(value) => print("Has value: {value}")
    case None => print("No value")
}

// Result type matching
function divide(a: int, b: int) -> Result<int, string> {
    if b == 0 {
        return Err("Cannot divide by zero")
    }
    return Ok(a / b)
}

match divide(10, 2) {
    case Ok(result) => print("Division result: {result}")
    case Err(error) => print("Error: {error}")
}

🛡️ Guard Conditions and Advanced Patterns

Complex Guard Conditions

let temperature = 25
let humidity = 60
let season = "summer"

match (temperature, humidity, season) {
    case (t, h, "summer") if t > 30 && h > 70 => print("Very hot and humid")
    case (t, h, "summer") if t > 25 && h < 50 => print("Warm and dry")
    case (t, _, "winter") if t < 0 => print("Very cold")
    case (t, h, _) if t >= 20 && t <= 25 && h >= 40 && h <= 60 => print("Pleasant weather")
    case _ => print("Regular weather")
}

Functional Pattern Matching

// Recursive pattern matching for list processing
function listSum(list: [int]) -> int {
    match list {
        case [] => 0
        case [first, ...rest] => first + listSum(rest)
    }
}

// Binary tree traversal
enum Tree<T> {
    Empty,
    Node(value: T, left: Tree<T>, right: Tree<T>)
}

function traverseTree<T>(tree: Tree<T>) {
    match tree {
        case Tree.Empty => {
            // Do nothing
        }
        case Tree.Node(value: value, left: left, right: right) => {
            traverseTree(left)
            print("Node value: {value}")
            traverseTree(right)
        }
    }
}

print("List sum: {listSum([1, 2, 3, 4, 5])}")  // 15

⚡ Advanced Control Flow Patterns

Combining Loops with Pattern Matching

let taskList = [
    { type: "email", priority: 1, content: "Check meeting schedule" },
    { type: "call", priority: 3, content: "Customer consultation" },
    { type: "document", priority: 2, content: "Write report" }
]

for task in taskList {
    match task {
        case { type: "email", priority: 1, content } => {
            print("Urgent email processing: {content}")
        }
        case { type: taskType, priority, content } if priority <= 2 => {
            print("Important {taskType} task: {content}")
        }
        case { type, content } => {
            print("Regular {type} task: {content}")
        }
    }
}

Error Handling and Control Flow

// try-catch style error handling
function safeFileRead(filename: string) -> Result<string, string> {
    if !filename.endsWith(".txt") {
        return Err("Only text files are supported")
    }
    
    // File reading simulation
    if Math.random() > 0.7 {
        return Err("File not found")
    }
    
    return Ok("File content here")
}

// Control flow with error handling
for filename in ["data.txt", "config.json", "readme.txt"] {
    match safeFileRead(filename) {
        case Ok(content) => {
            print("Successfully read: {filename}")
            print("Content: {content}")
            // Continue to next file on success
        }
        case Err(errorMessage) => {
            print("Error ({filename}): {errorMessage}")
            if errorMessage.contains("supported") {
                print("Unsupported file format, skipping")
                continue  // Continue to next file
            } else {
                print("Critical error, stopping processing")
                break     // Stop entire processing
            }
        }
    }
}

Conditional Execution Chains

// Conditional chaining
function processUser(userId: int) -> Result<string, string> {
    let userData = match getUserFromDatabase(userId) {
        case Ok(data) => data
        case Err(error) => return Err("User fetch failed: {error}")
    }
    
    let validationResult = match validateUser(userData) {
        case Ok(_) => ()
        case Err(error) => return Err("Validation failed: {error}")
    }
    
    let processResult = match processUserData(userData) {
        case Ok(result) => result
        case Err(error) => return Err("Processing failed: {error}")
    }
    
    return Ok("Processing complete: {processResult}")
}

// Monadic chaining style
function monadicProcess(userId: int) -> Result<string, string> {
    return getUserFromDatabase(userId)
        .andThen(validateUser)
        .andThen(processUserData)
        .map(result => "Processing complete: {result}")
}

🎯 Optimization and Best Practices

1. Conditional Optimization

// Bad: Nested conditions
let score = 85
if score >= 90 {
    print("Grade A")
} else {
    if score >= 80 {
        print("Grade B")
    } else {
        if score >= 70 {
            print("Grade C")
        } else {
            print("Grade F")
        }
    }
}

// Good: Using match
let grade = match score {
    case 90..=100 => "A"
    case 80..=89 => "B"
    case 70..=79 => "C"
    case _ => "F"
}
print("Grade {grade}")

2. Early Return Pattern

function registerUser(name: string, email: string, age: int) -> Result<string, string> {
    // Early validation and return
    if name.length() == 0 {
        return Err("Name is required")
    }
    
    if !email.contains("@") {
        return Err("Valid email is required")
    }
    
    if age < 0 || age > 120 {
        return Err("Valid age is required")
    }
    
    // Process only when all validations pass
    let user = createNewUser(name, email, age)
    return Ok("User registration complete: {user.id}")
}

3. Leveraging Pattern Matching

// Express complex business logic with patterns
enum OrderStatus {
    Created,
    PaymentComplete,
    Shipping,
    Delivered,
    Cancelled
}

function processOrder(status: OrderStatus, paymentAmount: int, isVip: bool) -> string {
    match (status, paymentAmount, isVip) {
        case (OrderStatus.Created, _, _) => "Please proceed with payment"
        case (OrderStatus.PaymentComplete, amount, true) if amount > 100000 => {
            "VIP customer express shipping preparation"
        }
        case (OrderStatus.PaymentComplete, amount, _) if amount > 50000 => {
            "Regular shipping preparation"
        }
        case (OrderStatus.PaymentComplete, _, _) => "Standard shipping preparation"
        case (OrderStatus.Shipping, _, true) => "VIP shipping tracking service"
        case (OrderStatus.Shipping, _, _) => "In shipping"
        case (OrderStatus.Delivered, _, _) => "Delivery complete"
        case (OrderStatus.Cancelled, _, _) => "Order cancelled"
    }
}

Topaz control flow is powerful and expressive. Combine conditionals, loops, and pattern matching appropriately to write readable and maintainable code! 🚀