We are currently working on new rules for what content should and shouldn't be allowed on this website, and are looking for feedback! See Esolang:2026 topicality proposal to view and give feedback on the current draft.
Algebroire
Algebroire (Official pronounciation: [ˈaldʒɪbɹɯ̯ɐɾ]) is a programming language designed by PSTF.
It is greatly inspired by Esomath and APL.
Basic Mathematical Things
Data storage
Variables are declared with := and reassigned by ←. For example,
x := 10 x ← 20
If you don't want to declare with initial value, you can use ∈, for example,
x ∈ Nat
A variable can be represented by a name made up of multiple symbols, and the same goes for sets, so we’ve pretty much stopped using double-struck capital letters. For example, Nat represents the set of natural numbers, Int represents integers, Rat represents rational numbers, Alg represents algebraic numbers (numbers that can be expressed with a finite number of roots), Float represents real numbers, and Comp represents complex numbers. Similarly, Str stands for strings, Bool for boolean values, Null for null (it's not equal to ∅), Lambda for functions, List for lists, Set for sets, Dict for dictionaries, Tuple for typles, Vec for vectors, and so on.
Function Definition
The most important thing in standard algebraic language is functions, and Algebroire is no different. Here is the syntax for defining functions.
function_name(argument) := {body}
For example,
F(n) := { 0 if n = 0;
1 if n = 1;
F(n−1)+F(n−2) otherwise }
And you can also "declare" a function without body:
function_name : argument types → returning type
For example,
F : Nat → Nat
F(n) := { 0 if n = 0;
1 if n = 1;
F(n−1)+F(n−2) otherwise }
And we even have lambda functions:
arguments |→ return_expression
Evaluation is pure and demand-driven. Definitions do not mutate.
E where arg1 := v1, arg2 := v2, ...
This is a temporary expression. It uses the parameters defined after 'where' when evaluated, and they are discarded once the evaluation is complete and the result is returned.
Piecewise Expressions
{ E₁ if C₁; E₂ if C₂; E₀ otherwise }
This is a piecewise expression. It evaluates into different expressions if conditions are met. If no conditions are met, then evaluates into E₀. The Fibonacci function mentioned above uses this expression.
Big Expressions and D&I stuffs
The “big expression” referred to here doesn’t mean it has a large value, but that it has a symbol that usually appears bigger than regular symbols in LaTeX, like sum, product, coproduct, integral, etc.
In plain text mode, since it’s impossible to accurately place the top and bottom markers, we use some special symbols.
∑_{i=m}^{n} E means adding up the results of E for values from m to n. If you replace ∑ with ∏, it means multiplying the results of E for values from m to n.
∫_{a}^{b} E dx is a definite integral function. We don't support indefinite integral one now.
d/dx E, ∂E/∂x, and E′ represent the differential, partial derivative, and derivative of E, respectively. Taking the derivative of any constant gives 0. Taking the derivative of e^x gives e^x.
lim_{x→a} E represents the value of E (an expression in terms of x) as x gradually approaches a. For example, the value of lim_{x→∞} 1/2^x is 2.
{ x ∈ S | P(x) } and { E | x ∈ S } are both set comprehensions. The first one represents generating a set containing only P(x) for all x in S, while the second one generates a set of all expressions E for x that belong to S.
∀ x ∈ S, P(x) and ∃ x ∈ S : P(x) represent, respectively, all the values in S that make P(x) true and whether there exists an x that makes P(x) true.
Matrices
A = [ a₁₁ a₁₂;
a₂₁ a₂₂ ]
This defines a matrix. We recommend to use the syntax above to make the matrix readable.
Aᵀ, A⁻¹, AB, and det(A) are all matrix transformations, with Aᵀ being the most common matrix transpose.
Vectors
x := *(1, 2, 3)
Vectors are declared like this. Only those with preceeding asterisks can be called vector in Algebroire, while those without it should be called "tuple".
x · y, ‖x‖
These are vector operations. It should be mentioned that x·y is not equal to x×y in vector.
More Data Types
There are also characters, units, results, ports, and threads.
Result(α, ε) # OK(alpha) or Error(epsilon) Task(α) # concurrent computation IO(α)
Programming Things
IO and do
print : α → IO(Unit) readLine : IO(String) readFile : String → IO(String) writeFile : String × String → IO(Unit) args : IO(List(String)) getEnv : String → IO(String) exit : Int → IO(⊥) return : α → IO(α)
A do block sequences effects. Use ← for effectful bind, := for pure local definitions, and ⇐ for assignment to a mutable local.
For example,
main : IO(Unit)
main := do
print("What is your name?")
name ← readLine
print("Hello, " + name + "!")
If main : IO(α), it is executed. If main : α, it is evaluated and printed.
Loops
Algebroire already has these:
sumTo(n) := ∑_{i=1}^{n} i
squares := [ i² | i ∈ 1..n ]
For effectful programming, Algebroire adds for, while, and repeat.
for i ∈ 1..10 do print(i) while x < 100 do print(x) x ⇐ x + 1 repeat line ← readLine until line = "quit"
Loop rules:
- for i ∈ S do E iterates over a finite list, range, or set.
- If the body has type IO(α), the loop has type IO(List(α)); as a statement, the result is discarded.
- while C do E repeats while C is true and returns IO(Unit).
- break exits the nearest loop; continue skips to the next iteration.
- Mutable locals are scoped to the nearest do block and desugar to explicit state.
Other programming constructs
Pattern Matching
length : List(α) → Nat length([]) := 0 length(x : xs) := 1 + length(xs) map : (α → β) × List(α) → List(β) map(f, []) := [] map(f, x : xs) := f(x) : map(f, xs)
Records
Point := { x : Float, y : Float }
p := { x: 1, y: 2 }
p.x
Modules and Imports
module Math {
π := 3.141592653589793
sin : Float → Float
cos : Float → Float
}
import Math
Error Handling
parseInt : String → Result(Int, String)
safeDiv : Float × Float → Result(Float, String)
safeDiv(a, b) := {
Ok(a ÷ b) if b ≠ 0;
Error("division by 0") otherwise
}
Or maybe...
try
text ← readFile("data.txt")
print(text)
catch e
print("error: " + e)
Command-line and environment
main := do
argv ← args
print("arguments: " + show(argv))
home ← getEnv("HOME")
print("home: " + home)
Examples
Fibonacci
φ := (1 + √5) / 2 F(n) := round( (φⁿ − (−φ)⁻ⁿ) / √5 )
Sieve of Erathosthenes
sieve : Nat → List(Nat)
sieve(N) := [ n | n ∈ 2..N, ¬composite[n] ]
where
var composite := array(N + 1, false)
for p ∈ 2..⌊√N⌋ do
if ¬composite[p] then
for m ∈ p²..N step p do
composite[m] ⇐ true
Sudoku Solver
solve : Grid → Option(Grid)
solve(g) :=
if complete(g) then Some(g)
else first([ solve(g′) | (i, j) := nextEmpty(g),
d ∈ 1..9,
valid(g, i, j, d),
g′ := set(g, i, j, d) ])
Turing-Completeness Proof
bfFast : String × String → IO(String)
bfFast(prog, inp) := do
jumps := matchBrackets(prog) // pure binding inside do
tape := array(30000, 0)
var ptr := 0
var pos := 0
var ins := chars(inp)
var out := ""
while pos < |prog| do
c := prog[pos]
if c = '>' then ptr ⇐ ptr + 1
else if c = '<' then ptr ⇐ ptr − 1
else if c = '+' then tape[ptr] ⇐ (tape[ptr] + 1) mod 256
else if c = '-' then tape[ptr] ⇐ (tape[ptr] − 1) mod 256
else if c = '.' then out ⇐ out ++ [chr(tape[ptr])]
else if c = ',' then
if ¬empty(ins) then do
tape[ptr] ⇐ ord(head(ins))
ins ⇐ tail(ins)
else if c = '[' then
if tape[ptr] = 0 then pos ⇐ jumps[pos]
else if c = ']' then
if tape[ptr] ≠ 0 then pos ⇐ jumps[pos]
pos ⇐ pos + 1
return out