Waxaan qoraynaa oon dib uhabeyn ku wadnaa docs oo af-soomaali ku qoran, ka qeybqaadasho raac lifaaqaan...Contribution guidelines

Loops in Soplang

Loops are essential programming constructs that allow you to execute a block of code repeatedly. Soplang provides several types of loops to handle different iteration needs.

For Loops

The ku_celi (for) loop is used to iterate over a sequence (like a list, string, or range) or any iterable object. The name comes from the Somali phrase "ku celi" which means "repeat".

Basic For Loop

basic_for_loop.sop
// Iterating over a list
door fruits = ["apple", "banana", "orange", "mango"]

ku_celi fruit ku dhex jira fruits {
    qorln(fruit)
}

/* Output:
apple
banana
orange
mango
*/

For Loop with Range

You can use the tiro_taxane (range) function to iterate over a sequence of numbers.

for_loop_range.sop
// Iterating over a range of numbers
ku_celi i ku dhex jira tiro_taxane(5) {
    qorln(i)
}

/* Output:
0
1
2
3
4
*/

// Range with start, stop, and step parameters
ku_celi i ku dhex jira tiro_taxane(2, 10, 2) {
    qorln(i)
}

/* Output:
2
4
6
8
*/

For Loop with Index

To access both the index and value during iteration, you can use the tirsan (enumerate) function.

for_loop_index.sop
// Iterating with index
door fruits = ["apple", "banana", "orange", "mango"]

ku_celi (index, fruit) ku dhex jira tirsan(fruits) {
    qorln(index + ": " + fruit)
}

/* Output:
0: apple
1: banana
2: orange
3: mango
*/

For Loop with Dictionary

You can iterate over the keys, values, or key-value pairs of a dictionary.

for_loop_dictionary.sop
// Dictionary iteration
door person = {
    "name": "Ahmed",
    "age": 30,
    "city": "Mogadishu",
    "occupation": "Engineer"
}

// Iterating over keys
qorln("Keys:")
ku_celi key ku dhex jira person.fureyaal() {
    qorln(key)
}

// Iterating over values
qorln("
Values:")
ku_celi value ku dhex jira person.qiyamyaal() {
    qorln(value)
}

// Iterating over key-value pairs
qorln("
Key-Value Pairs:")
ku_celi (key, value) ku dhex jira person.shayada() {
    qorln(key + ": " + value)
}

While Loops

The inta (while) loop executes a block of code as long as a specified condition is true. The name comes from the Somali word "inta" which means "while" or "as long as".

Basic While Loop

basic_while_loop.sop
// Basic while loop
door count = 1

inta count <= 5 {
    qorln(count)
    count += 1
}

/* Output:
1
2
3
4
5
*/

While Loop with Condition Update

while_loop_condition.sop
// Processing a list with while loop
door numbers = [10, 20, 30, 40, 50]
door index = 0

inta index < numbers.dherer() {
    qorln("Number at index " + index + ": " + numbers[index])
    index += 1
}

/* Output:
Number at index 0: 10
Number at index 1: 20
Number at index 2: 30
Number at index 3: 40
Number at index 4: 50
*/

Infinite While Loop with Break

You can create an infinite loop using inta true and exit it using the jebi (break) statement when a certain condition is met.

while_infinite_break.sop
// Infinite loop with break
door count = 1

inta true {
    qorln(count)
    count += 1
    
    haddii count > 5 {
        qorln("Breaking the loop")
        jebi  // Exit the loop
    }
}

qorln("Loop ended")

/* Output:
1
2
3
4
5
Breaking the loop
Loop ended
*/

Do-While Loops

The samee_inta (do-while) loop is similar to the while loop, but it executes the code block at least once before checking the condition. The name combines "samee" (do) and "inta" (while) in Somali.

Basic Do-While Loop

basic_do_while.sop
// Basic do-while loop
door count = 1

samee {
    qorln(count)
    count += 1
} inta count <= 5

/* Output:
1
2
3
4
5
*/

Do-While vs While

The key difference between samee_inta and inta is that do-while always executes the code block at least once, even if the condition is initially false.

do_while_vs_while.sop
// Comparing do-while and while when condition is initially false
door x = 10

// Do-while loop (executes once)
qorln("Do-while loop:")
samee {
    qorln("x = " + x)
    x += 1
} inta x < 10

// While loop (doesn't execute)
qorln("
While loop:")
x = 10  // Reset x
inta x < 10 {
    qorln("x = " + x)
    x += 1
}

/* Output:
Do-while loop:
x = 10

While loop:
*/

User Input Validation

Do-while loops are particularly useful for input validation where you want to prompt the user at least once and then repeat until valid input is received.

do_while_input_validation.sop
// Input validation with do-while
door valid_input = false
door number = 0

samee {
    door input = akhri_weydii("Enter a positive number: ")
    
    isku_day {
        number = tiro_u_badal(input)
        
        haddii number > 0 {
            valid_input = true
            qorln("Valid input received: " + number)
        } kale {
            qorln("Number must be positive. Try again.")
        }
    } qabso {
        qorln("Invalid input. Please enter a number.")
    }
} inta !valid_input

qorln("Processing with number: " + number)

Loop Control Statements

Soplang provides several statements to control the flow of loops: jebi (break), sii_wad (continue), and ka_bax (return).

Break Statement

The jebi statement terminates the loop and transfers control to the statement following the loop.

break_statement.sop
// Using break to exit a loop early
door numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

qorln("Finding the first number greater than 5:")
ku_celi num ku dhex jira numbers {
    haddii num > 5 {
        qorln("Found: " + num)
        jebi  // Exit the loop
    }
    qorln("Checking: " + num)
}

/* Output:
Finding the first number greater than 5:
Checking: 1
Checking: 2
Checking: 3
Checking: 4
Checking: 5
Found: 6
*/

Continue Statement

The sii_wad statement skips the rest of the current iteration and continues with the next iteration of the loop.

continue_statement.sop
// Using continue to skip certain iterations
door numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

qorln("Printing only odd numbers:")
ku_celi num ku dhex jira numbers {
    haddii num % 2 == 0 {
        sii_wad  // Skip even numbers
    }
    qorln(num)
}

/* Output:
Printing only odd numbers:
1
3
5
7
9
*/

Nested Loops and Break/Continue

When using jebi or sii_wad in nested loops, they affect only the innermost loop that contains them.

nested_loops_control.sop
// Nested loops with break and continue
qorln("Multiplication table with some values skipped:")

ku_celi i ku dhex jira tiro_taxane(1, 4) {
    ku_celi j ku dhex jira tiro_taxane(1, 4) {
        // Skip when product is odd
        haddii (i * j) % 2 != 0 {
            sii_wad
        }
        
        qorln(i + " x " + j + " = " + (i * j))
        
        // Break inner loop when product is 6
        haddii i * j == 6 {
            qorln("Breaking inner loop")
            jebi
        }
    }
    qorln("---")
}

/* Output:
Multiplication table with some values skipped:
1 x 2 = 2
---
2 x 1 = 2
2 x 2 = 4
2 x 3 = 6
Breaking inner loop
---
3 x 2 = 6
Breaking inner loop
---
*/

Best Practices

  • Choose the Right Loop Type

    Select the appropriate loop type based on your specific needs:

    • Use ku_celi (for) when you know the number of iterations in advance
    • Use inta (while) when you need to loop until a condition is met
    • Use samee_inta (do-while) when you need to execute the loop at least once
    right_loop_type.sop
    // Good practice: Using the right loop type
    
    // For known number of iterations
    ku_celi i ku dhex jira tiro_taxane(5) {
        // Process with index i
    }
    
    // For unknown number of iterations with condition check first
    door input = ""
    inta input != "quit" {
        input = akhri_weydii("Enter command (type 'quit' to exit): ")
        // Process input
    }
    
    // For unknown number of iterations with at least one execution
    samee {
        door input = akhri_weydii("Enter a value: ")
        // Process input
    } inta !is_valid(input)
  • Avoid Infinite Loops

    Always ensure that your loop condition will eventually become false, or include a break statement to exit the loop.

    avoid_infinite_loops.sop
    // Bad practice: Potential infinite loop
    door count = 10
    inta count > 0 {
        qorln(count)
        // Forgot to decrement count!
    }
    
    // Good practice: Ensure loop termination
    door count = 10
    inta count > 0 {
        qorln(count)
        count -= 1  // Ensure the condition will eventually be false
    }
  • Use For Loops for Iterables

    Prefer ku_celi (for) loops when iterating over collections instead of manually tracking indices with while loops.

    use_for_loops.sop
    // Bad practice: Using while loop for iteration
    door fruits = ["apple", "banana", "orange"]
    door i = 0
    inta i < fruits.dherer() {
        qorln(fruits[i])
        i += 1
    }
    
    // Good practice: Using for loop for cleaner iteration
    door fruits = ["apple", "banana", "orange"]
    ku_celi fruit ku dhex jira fruits {
        qorln(fruit)
    }
  • Keep Loops Simple

    Keep the body of your loops as simple as possible. If the loop body is complex, consider extracting it into a separate function.

    simple_loops.sop
    // Bad practice: Complex loop body
    ku_celi user ku dhex jira users {
        // Complex logic with many conditions and operations
        // ...
        // ...
        // Many lines of code
    }
    
    // Good practice: Extract complex logic into a function
    howl process_user(user) {
        // Complex logic
        // ...
    }
    
    ku_celi user ku dhex jira users {
        process_user(user)
    }