RiX at a glance
RiX uses familiar expression syntax, then adds notation for ideas that mathematical programs routinely need: exact values, intervals, structured collections, explicit data flow, units, semantic types, and controlled evaluation.
Exact values first
1/3 + 1/6 ## 1/2
1..3/4 ## mixed number: 7/4
0.#3 ## repeating decimal: 1/3
2:5 ## rational interval
RiX delegates its foundational exact arithmetic to RatMath core types. Approximation is an explicit extension boundary rather than the default numeric model.
Names reveal intent
Lowercase-leading names are user values. Uppercase-leading names are callable/system-facing values. Adjacency can therefore read mathematically:
x := 7
Sq(x) -> x^2
3x^2 ## 3 * x^2
Sq 3x ## Sq(3*x)
Explicit calls are always available. The case convention helps the parser distinguish mathematical multiplication from application.
Functions can prepare their inputs
Positive(x) ?- [x > 0] -> x
Nonzero(x) ?!- [x != 0] -> x
?- is a soft preparation gate: failure means “this function does not accept that candidate.” ?!- is strict and propagates failure. Ordered variants combine into multifunctions, letting dispatch be written in RiX rather than hidden in host code.
Containers announce what they are
[1, 2, 3] ## array
{| 1, 2, 3 |} ## set
{= name = "Ada" } ## map
{: 2, 3 } ## tuple
{:2x2: 1, 2; 3, 4 } ## tensor
{; x := 2; x^3 } ## execution block
{? x > 0 ? x; -x } ## case
The brace sigil is a compact type marker. A reader can tell a block, map, set, tuple, tensor, loop, case, mutation, or symbolic specification apart at its opening delimiter.
Pipes make traversal visible
Double(x) -> 2x
Positive(x) -> x > 0
[1, -2, 3] |>> Double ## map
[1, -2, 3] |>? Positive ## filter
[1, 2, 3] |>: @+[2] ## reduce
Traversal callbacks can receive (value, locator, source). The locator is a one-based index for sequences, a key for maps, and an index tuple for tensors.
Generators can stay lazy
finite := [1, |+ 2, |; 6]
lazy := [1, |+ 2, |^ 6]
firstFive := [1, |+ 1, |^ _][1:5]
Generator clauses describe seeds, recurrence/history, transforms, filters, and stopping. Lazy sequences compute and cache only what a consumer asks for.
Units and exact generators compose
distance := 120~[m]
elapsed := 30~[s] + 2~[min]
speed := .ConvertUnit(distance / elapsed, "m/s")
z := 1 + 1~{i}
c := .Complex.Cayley(z)
c.Cartesian()
Scientific unit sugar (~[...]) resolves through the configurable .Units collection. Mathematical/exact generator sugar (~{...}) resolves through .Exact. Both participate in ordinary arithmetic dispatch.
Assignment says whether identity matters
RiX variables name cells. Its assignment family makes aliasing and update behavior visible:
| Form | Meaning |
|---|---|
x = y |
alias/rebind; variables can share a cell |
x := y |
fresh cell with a shallow copy |
x ~= y |
replace the value in the existing cell |
x ::= y |
fresh cell with a deep copy |
x ~~= y |
deep-copy into the existing cell |
That distinction matters for mutable structures, metadata, closures, and semantic values. The complete introduction develops the model progressively.
The system object is explicit
.Len([10, 20, 30])
.Warn("large interval", {= width = 12 })
.Units[:degC](20)
The leading dot is the system capability object. Hosts can construct and freeze it, add capabilities, or withhold groups for imported scripts. Operator functions are first-class too: @+ names addition, and @+[2] caps it to two incoming arguments.
Three ways to keep learning
- Follow the complete introduction when you want concepts and examples in teaching order.
- Use the syntax guide and methods guide while writing code.
- Read the developer guide when embedding or extending the parser/evaluator.