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! 🚀