What's Different From Traditional Programming

For programmers coming from C, Python, and everything else.

If you've written code in C, Python, or most anything else, Sanguis works differently. Here's what changes.

No control flow statements

TraditionalSanguis
if (x > 5) { ... }but x > 5.0 (gates a route)
for (i=0; i<N; i++)Route fires every tick - loop is implicit
while (cond)Route ticks until conditions fail
return valueemit value to target
function callRoute fires when conditions pass

There is no if. There is no for. There is no while. There is no return. The route is the only control flow. Conditions gate routes. Routes loop by firing repeatedly until conditions fail.

Two data types only

Traditional typesSanguis types
int, float, doublememory scalar (floating-point)
string, char*memory text (variable-length string)
boolUse scalar (0.0 = false, 1.0 = true)
struct, classNo structs or classes
int[], arraysNo arrays - use individual holds

There are no ints, no structs, no classes, no arrays. Scalars are floating-point. Text is strings. That's it.

Parallel by default

In traditional languages, code runs sequentially, one instruction after another. In Sanguis, all routes evaluate every tick, simultaneously. There is no sequential ordering.

TraditionalSanguis
Sequential executionParallel route evaluation every tick
Shared mutable state + locksSnapshot semantics, no races
Threads, async, goroutinesNot needed, parallelism is the default
Manual synchronizationEngine handles it via tick snapshots

All routes see the same snapshot at the start of the tick. Route A's emit to hold X is not visible to Route B's conditions in the same tick. Data races are eliminated by design.

Settling, not stepping

In traditional languages, you write a sequence of steps: do this, then that, then the other. In Sanguis, you describe state and rules. The engine settles the system tick by tick until it reaches a terminal state.

// Traditional: step-by-step
x = 1
y = x + 2
print(y)

// Sanguis: describe state and rules, engine settles
circuit Add {
  hold a : memory scalar = 0.0
  hold b : memory scalar = 0.0
  hold c : memory scalar = 0.0
  hold state : memory scalar = 0.0

  when start {
    but state = 0.0
    emit 1.0 to a
    emit 2.0 to b
    emit a + b to c
    emit c to screen
    emit 1.0 to state
  }
}

No assignment, data flows

// Traditional: x = 5
// Sanguis: emit 5.0 to x          (inside a route)

// Traditional: result = compute(input)
// Sanguis: emit compute(input) to result

The keyword to is the only operator that moves data. Everything else is either a hold declaration, a condition, or arithmetic inside an emit.

Programs are circuits, not functions

TraditionalSanguis
Files of functionsCircuits of holds and routes
main() starts, runs, exitsEngine ticks until terminal state
You manage state explicitlyHolds hold state; routes transform it
Solve problems step by stepDescribe state and rules, engine settles