Skip to content

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