Control Flow
This reference describes how to control the execution of Zigma programs through loops and conditional statements.
Conditionals
Block Form
Standard if and else blocks use a colon : and indentation. The else branch is optional.
if x > 0 m:
y = x * 2
else:
y = 0 m
Inline Form
For simple assignments, conditionals can be written as expressions. This is useful for capping values or setting defaults.
limit = 100 km/h
capped_speed = if v > limit as limit else v
Dimensional Homogeneity
Both branches of a conditional must return the exact same dimension. Zigma will trigger a compile-time error if you attempt to return different units from different branches.
// COMPILE ERROR: Branch dimensions do not match ([m] vs [s])
bad = if condition as 1 m else 1 s
Loops
Range-based for
Zigma uses range-based iteration using the .. operator. The loop variable automatically inherits the dimension and scale of the range.
for t in 0..10 s step 0.1:
// t is strictly [Time] in [seconds]
y = v0 * t - 0.5 * g * t^2
Syntax Rules:
* start..end: The range boundaries.
* unit: (Optional) The scale for the range.
* step: (Optional) The increment value. If omitted, the step is 1. The step value must share the same dimension as the range.
Implicit Vectorization (Preferred)
In Zigma, you should generally avoid for loops for simple mathematical transformations. If no mutation is needed, assigning a range directly to a variable is faster because Zigma will automatically vectorize the operation using SIMD hardware acceleration.
// PREFERRED: fully vectorized, SIMD-accelerated
t = 0..10 s step 0.1
y = v0*t - 0.5*g*t^2
// EXPLICIT LOOP: needed only if an iteration depends on a previous one
for t in 0..10 s step 0.1:
y := v0*t - 0.5*g*t^2
while Loops
The while loop executes as long as a condition is met. Variables updated within a while loop must be declared mutable using :=.
x := 100 m
while x > 0 m:
x := x - 1 m
Functions
Functions need
fn print(x):
print "This is x: {x:.2}"
fn add(x) ->: // This mean return any tensor
x + 1 as x
You can define dimension for arguments.
fn speed(d in m, t in s) -> m/s:
d / t
You can pass any shape Tensor as parameter or define an explicit one.
fn cross(a as (3), b as (3)) -> (3):
[a[2] * b[3] - a[3] * b[2], a[3] * b[1] - a[1] * b[3], a[1] * b[2] - a[2] * b[1]]
Scope Rules
Zigma uses Block Scoping. Variables defined inside a loop or conditional block are local to that block and cannot be accessed from the parent scope.
if condition:
a = 1
print a // COMPILE ERROR: 'a' is not defined in this scope
Accessing values outside blocks
To use a value calculated inside a block in the parent scope, you must declare a mutable variable in the parent scope first, then update it inside the block.
final_y := 0 m
for t in 0..10 s step 0.1:
final_y := v0*t - 0.5*g*t^2
print final_y // OK: Prints the last value calculated in the loop