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
| Traditional | Sanguis |
|---|---|
| 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 value | emit value to target |
| function call | Route 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 types | Sanguis types |
|---|---|
| int, float, double | memory scalar (floating-point) |
| string, char* | memory text (variable-length string) |
| bool | Use scalar (0.0 = false, 1.0 = true) |
| struct, class | No structs or classes |
| int[], arrays | No 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.
| Traditional | Sanguis |
|---|---|
| Sequential execution | Parallel route evaluation every tick |
| Shared mutable state + locks | Snapshot semantics, no races |
| Threads, async, goroutines | Not needed, parallelism is the default |
| Manual synchronization | Engine 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
| Traditional | Sanguis |
|---|---|
| Files of functions | Circuits of holds and routes |
| main() starts, runs, exits | Engine ticks until terminal state |
| You manage state explicitly | Holds hold state; routes transform it |
| Solve problems step by step | Describe state and rules, engine settles |