Loops
GX has loops for every situation — counting, iterating, filtering, and even building new data from loops.
While Loop
Repeat while a condition is true:
fn main() {
var count = 0
while (count < 5) {
print("count = {count}\n")
count++
}
print("Done!\n")
}
For-Range Loop
Count through a range of numbers. The range is inclusive on both ends:
fn main() {
// Prints 1, 2, 3, 4, 5
for (i = 1:5) {
print("i = {i}\n")
}
}
for (i = 1:5) means “i goes from 1 to 5, including 5.” No off-by-one headaches.
fn main() {
// Countdown
for (i = 10:1) {
print("{i}... ")
}
print("Liftoff!\n")
}
For-Each Loop
Iterate over every element in an array:
fn main() {
var fruits:str[4] = {"apple", "banana", "cherry", "date"}
for (var fruit in fruits) {
print("I like {fruit}\n")
}
}
Works with any array type:
fn main() {
var scores:i32[5] = {92, 87, 95, 78, 88}
var total = 0
for (var s in scores) {
total += s
}
print("Total: {total}\n")
print("Average: {total / 5}\n")
}
Filtered Iteration with where
Add a condition to skip elements:
fn main() {
var nums:i32[8] = {1, 2, 3, 4, 5, 6, 7, 8}
print("Even numbers: ")
for (var n in nums) where (n % 2 == 0) {
print("{n} ")
}
print("\n")
print("Greater than 5: ")
for (var n in nums) where (n > 5) {
print("{n} ")
}
print("\n")
}
No temporary arrays, no extra allocations — where filters inline.
Collect: Build Arrays from Loops
collect captures loop results into a new dynamic array:
fn main() {
var nums:i32[8] = {1, 2, 3, 4, 5, 6, 7, 8}
// Collect even numbers
var evens = for (n in nums) where (n % 2 == 0) collect n
print("Evens ({evens.len()}):")
for (i = 0:evens.len() - 1) {
print(" {evens.at(i)}")
}
print("\n")
// Collect with transformation
var doubled = for (n in nums) where (n <= 4) collect n * 2
print("Doubled ({doubled.len()}):")
for (i = 0:doubled.len() - 1) {
print(" {doubled.at(i)}")
}
print("\n")
evens.free()
doubled.free()
}
Break and Continue
Control loop flow:
fn main() {
// break: exit the loop early
print("Break example: ")
for (i = 1:10) {
if (i == 6) {
break
}
print("{i} ")
}
print("\n") // prints: 1 2 3 4 5
// continue: skip to next iteration
print("Continue example: ")
for (i = 1:10) {
if (i % 3 == 0) {
continue
}
print("{i} ")
}
print("\n") // prints: 1 2 4 5 7 8 10
}
Practical Example: Finding a Value
fn main() {
var data:i32[6] = {14, 27, 3, 91, 42, 8}
var target = 42
var found = false
for (var val in data) {
if (val == target) {
found = true
break
}
}
if (found) {
print("Found {target}!\n")
} else {
print("{target} not found\n")
}
}
Try it — Write a loop with
whereandcollectin the Playground.
Expert Corner
For-range is inclusive (for (i = 1:5) gives 1,2,3,4,5). This was a deliberate design choice — inclusive ranges are more intuitive for mathematical sequences, game loops (for (frame = 0:59) gives you 60 frames), and human-readable code. No < n vs <= n confusion.
collect is not magic — it’s a compile-time transform. The compiler generates a dynamic array with .init() and .push() calls inside the loop. You’re responsible for calling .free() on the result when you’re done. This keeps the language honest about allocations.
where filters happen inline with zero overhead — no intermediate array is created. The compiler emits a simple if check inside the loop body. It’s syntactic sugar that reads like English without costing performance.
par for exists for parallel iteration across CPU cores. It’s the same syntax with a par prefix: par for (i = 0:999) { ... }. The compiler generates threaded work distribution. That’s a topic for an advanced tutorial.