ReferenceControlArcReferenceLoops

Loops

Arc for loop reference for iterating over series, ranges, and conditions

Arc’s for loops iterate over series, count through ranges, and repeat until a condition is met. They live inside function bodies, where you do your actual computation.

The reactive layer (stages and flow statements) handles getting data to your functions. Loops handle processing that data once it arrives. For accumulating values across multiple executions, use stateful variables instead.

Iterating Over a Series

Use for to walk through each element of a series:

func sum_all() f64 {
    data := [1.0, 2.5, 3.7, 4.2]
    sum f64 := 0.0
    for x := data {
        sum = sum + x
    }
    return sum
}

Each iteration binds the next element to x. The loop ends when every element has been visited.

Index and Value

If you also need the position, declare two variables:

func find_peak() i32 {
    data := [3.1, 7.5, 2.0, 9.8, 1.4]
    peak f64 := 0.0
    peak_idx i32 := 0
    for i, x := data {
        if x > peak {
            peak = x
            peak_idx = i
        }
    }
    return peak_idx
}

The index starts at 0 and has type i32.

Range Loops

range generates a sequence of integers. It accepts one, two, or three arguments.

One Argument

range(end) counts from 0 up to (but not including) end:

// i takes values 0, 1, 2, 3, 4
for i := range(5) {
    // ...
}

Two Arguments

range(start, end) counts from start up to (but not including) end:

// i takes values 5, 6, 7, 8, 9
for i := range(5, 10) {
    // ...
}

Two-argument range(start, end) always counts upward (step defaults to +1). To count downward, use three arguments with a negative step. Writing range(10, 0) produces zero iterations because start is already past end.

Three Arguments

range(start, end, step) counts from start toward end, advancing by step:

// i takes values 0, 2, 4, 6, 8
for i := range(0, 10, 2) {
    // ...
}
// Counting down: i takes values 5, 3, 1, -1, -3
for i := range(5, -5, -2) {
    // ...
}

A negative step counts downward. The loop stops before reaching end.

Edge Cases

If the range is empty, the loop body never executes:

for i := range(0) {} // no iterations
for i := range(10, 5) {} // no iterations (start > end, step is positive)
for i := range(0, 10, -1) {} // no iterations (start < end, step is negative)

All range arguments must be integer types (i8, i16, i32, i64, u8, u16, u32, u64). Float values are not accepted.

Conditional Loops

A for with a condition repeats while the condition is non-zero:

func countdown(n i32) i32 {
    sum i32 := 0
    for n > 0 {
        sum = sum + n
        n = n - 1
    }
    return sum
}

The condition is checked before each iteration. If it’s false from the start, the body never runs.

Infinite Loops

A bare for repeats until you break out:

func next_power_of_two(n i32) i32 {
    val i32 := 1
    for {
        if val >= n {
            break
        }
        val = val * 2
    }
    return val
}

Break and Continue

break exits the loop immediately. continue skips to the next iteration.

Break

Stop processing a series once you hit a sentinel value:

func sum_until_negative() i32 {
    data := [5, 3, 8, -1, 10]
    sum i32 := 0
    for x := data {
        if x < 0 {
            break
        }
        sum = sum + x
    }
    return sum // 16 (5 + 3 + 8, stops before -1)
}

Continue

Skip elements that don’t meet a criterion:

func sum_positive() i32 {
    data := [5, -3, 8, -1, 10]
    sum i32 := 0
    for x := data {
        if x < 0 {
            continue
        }
        sum = sum + x
    }
    return sum // 23 (5 + 8 + 10, skips negatives)
}

Nested Loops

break and continue apply to the innermost enclosing loop:

func count_valid_pairs() i64 {
    count i64 := 0
    for i := range(3) {
        for j := range(10) {
            if j >= 2 {
                break // exits inner loop only
            }
            count = count + 1
        }
        // outer loop continues normally
    }
    return count // 6 (3 outer * 2 inner)
}

Loop Variables

Loop variables (i, x, etc.) are scoped to the loop body and cannot be reassigned:

for i := range(5) {
    i = 10 // Error: cannot assign to loop variable 'i'
}

They also cannot be accessed after the loop ends.

Summary

FormSyntaxDescription
Series (value)for x := data { }Iterate over each element
Series (index, value)for i, x := data { }Iterate with position
Range (1 arg)for i := range(end) { }Count from 0 to end
Range (2 args)for i := range(start, end) { }Count from start to end
Range (3 args)for i := range(start, end, step) { }Count with custom step
Conditionalfor condition { }Repeat while condition is non-zero
Infinitefor { }Repeat until break