XIOM Concepts -- For Programmers from Other Languages¶
You already know how to program. This guide maps the concepts you know to how they work in XIOM. No fluff. Just translations.
If You're Coming From...¶
| Language | Closest mental model to XIOM |
|---|---|
| Rust | Ownership, Result/Option, traits-as-interfaces, derive macros -> derive[]. You lose lifetimes and gain contracts. |
| Go | Structural interfaces (same!), if err != nil -> Result[T,E], goroutines -> spawn. You lose GC and null. |
| C++ | RAII, move semantics, templates -> generics, std::optional -> Option[T]. You lose inheritance, exceptions, and header files. |
| Python | Type hints become mandatory. Optional -> Option[T]. No None. No exceptions. |
| Java | Interfaces without implements. No null. No exceptions. No class -- use structs + methods. |
| C# | Properties become fields plus methods, delegates become fn types, Task maps to async/await and spawn. No null, no exceptions, no classes or inheritance -- use structs, composition and structural interfaces. |
| JavaScript | undefined doesn't exist. Promises -> async/await. No prototype chain. No this. |
1. No Null -- Option[T] Instead¶
Every language has null. XIOM doesn't.
| Language | Absence |
|---|---|
| Java | null -- crashes at runtime |
| C# | null; nullable reference types are opt-in annotations, not a language-wide guarantee |
| Python | None -- crashes at runtime |
| Rust | Option<T> -- compiler enforces handling |
| XIOM | Option[T] -- compiler enforces handling |
// Instead of: String name = null;
let name: Option[Str] = None;
// Instead of: if (name != null) { use(name); }
match name {
Some(n) => io.println("Hello, " + n),
None => io.println("no name"),
};
You cannot accidentally use None as a value. The compiler rejects it.
2. No Exceptions -- Result[T, E] Instead¶
Every language has exceptions. XIOM doesn't.
| Language | Error handling |
|---|---|
| Java/C# | try/catch -- invisible control flow |
| Python | try/except -- any line can throw |
| Go | if err != nil -- explicit but verbose |
| Rust | Result<T, E> + ? -- explicit, clean |
| XIOM | Result[T, E] + ? -- explicit, clean |
// Instead of: throw new IOException("file not found");
fn read_config(path: Str) -> Result[Config, Str] {
let file = io.read_file(path)?; // ? returns the error immediately
let config = parse(file)?;
return Ok(config);
}
// At the call site -- must handle both cases
match read_config("config.json") {
Ok(c) => use(c),
Err(e) => io.println("error: " + e),
};
The ? operator is try! from Rust, try from Zig. It returns Err(...) immediately if the value is an error. Clean propagation without invisible control flow.
3. Ownership -- No GC, No Manual free()¶
| Language | Memory management |
|---|---|
| Java/C#/Python/Go | Garbage collector -- pauses, unpredictable |
| C | malloc/free -- manual, error-prone |
| C++ | RAII + smart pointers -- complex rules |
| Rust | Ownership + borrow checker + lifetimes -- powerful but complex |
| XIOM | Ownership + lexical scope borrowing -- no lifetime annotations |
// A value has ONE owner. Assignment moves ownership.
let a = Vec.new();
let b = a; // a MOVED to b -- a is now invalid
// a.push(1); // COMPILE ERROR: a was moved
// Borrow temporarily with & (read) or &mut (write)
read_only(&b); // b is borrowed -- still valid after
mutate(&mut b); // exclusive write borrow
// Clone to duplicate
let c = b.clone(); // explicit copy -- both valid
The key difference from Rust: No lifetime annotations. Ever. Borrows expire at the end of the block where they're created. You can see when a borrow ends by looking at the braces.
Coming from C#: using and IDisposable give deterministic cleanup for the resources you wrap explicitly. XIOM applies a lifetime rule like that to every owned value -- memory is freed when its owner leaves scope -- and duplication is always explicit with .clone().
4. Structs + Methods -- No Classes, No Inheritance¶
XIOM has no class, no extends, no implements, no virtual, no override, no protected. Here's what you use instead:
| OOP Concept | XIOM Equivalent |
|---|---|
class |
type (struct) |
extends / inheritance |
Not supported. Use composition or interfaces. |
implements |
Not needed. Any type with matching methods satisfies the interface automatically. |
public / private |
pub keyword. Private is the default. |
protected |
Not supported. Use separate modules. |
virtual / override |
Not supported. Use structural interfaces for polymorphism. |
abstract class |
Not supported. Use interfaces. |
| Constructor | fn TypeName.new() -> Type method |
this / self |
self is implicit -- access fields directly |
static method |
Free function fn function_name() |
| Property getter/setter | Direct field access. Use methods for logic. |
// Instead of: class Point { private float x; public float getX()... }
type Point = {
x: Float64; // private by default
y: Float64;
} derive[Eq, Clone, Display] // auto-generate equality, clone, to-string
pub fn Point.distance(other: &Point) -> Float64 {
// self is implicit -- x means self.x
let dx = x - other.x;
let dy = y - other.y;
return dx * dx + dy * dy;
}
5. Polymorphism -- Structural Interfaces¶
XIOM has no inheritance. Polymorphism works through structural interfaces -- if a type has the required methods, it satisfies the interface. No declaration needed.
// Define what "comparable" means
interface Comparable {
fn compare(other: &Self) -> Int; // -1, 0, 1
}
// Create two completely unrelated types
type Score = { value: Int; }
type Temperature = { kelvin: Float64; }
// Implement compare for each -- NO "implements" keyword needed
fn Score.compare(other: &Score) -> Int { return value - other.value; }
fn Temperature.compare(other: &Temperature) -> Int { ... }
// A generic function that works with ANY comparable type
fn max[T: Comparable](a: T, b: T) -> T {
if a.compare(&b) > 0 { return a; }
return b;
}
let winner = max(Score{ value: 10 }, Score{ value: 20 });
// Both Score and Temperature satisfy Comparable automatically
This is Go's interface model. It's also how Python's duck typing works, except compile-time verified.
6. Contracts -- In the Language, Not in Comments¶
No mainstream language ships contracts as part of its core syntax. Design by Contract has a long lineage -- Eiffel had it in 1986, and Ada 2012/SPARK, Dafny and Frama-C pushed it further with static verification. XIOM's bet is packaging: contracts in the core language of a systems compiler, enforced at runtime by default and available to verification tooling for supported properties. The website's Prior art and trade-offs page covers the comparison.
fn divide(a: Float64, b: Float64) -> Float64
requires: b != 0.0 // PRE-CONDITION: caller must guarantee this
ensures: result * b == a // POST-CONDITION: implementation must guarantee this
{
return a / b;
}
type Health = {
current: Int;
maximum: Int;
invariant: current >= 0; // TYPE INVARIANT: always true
invariant: current <= maximum;
}
| Contract | Like... | But... |
|---|---|---|
requires: |
assert() at function entry |
Part of the language, enforced by the toolchain instead of stripped by convention |
ensures: |
assert() at function exit + unit test |
Enforced on every return path, and exported to verification tooling |
invariant: |
A database CHECK constraint | On every mutation, checked at compile time or runtime |
When a contract is violated at runtime, the program panics with the exact contract that failed, the file, and the line number -- an error a unit test would only catch if it exercised that path with those values.
7. Public / Private -- Module-Based Visibility¶
| Language | Privacy model |
|---|---|
| Java/C# | public/private/protected on classes and members |
| C++ | public:/private: sections in class body |
| Python | _convention -- not enforced |
| Rust | pub -- everything private by default |
| XIOM | pub -- everything private by default |
module myproject.data;
pub type User = { // visible outside this module
name: Str;
email: Str;
} derive[Clone]
pub fn User.validate() -> Bool { // visible outside
return email.contains("@");
}
fn hash_email(user: &User) -> Int { // PRIVATE -- only visible in this module
// ...
}
No protected. No friend. No package-private. Just pub or private.
8. Generics -- Like Templates, But Type-Checked Before Instantiation¶
| Language | Generics |
|---|---|
| C++ | Templates -- duck-typed, errors at instantiation |
| Java | Type erasure -- limited, no primitives |
| C# | Reified generics -- better, still class-based |
| Rust/Go | Monomorphised -- zero-cost, checked at definition |
| XIOM | Monomorphised -- zero-cost, checked at definition |
// Instead of: template<typename T> T max(T a, T b) { return a > b ? a : b; }
fn max[T: Comparable](a: T, b: T) -> T {
if a > b { return a; }
return b;
}
// Works with any type that satisfies Comparable
let m1 = max(10, 20); // T = Int
let m2 = max(1.5, 2.7); // T = Float64
let m3 = max(Score{value:10}, Score{value:20}); // T = Score
The [T: Comparable] constraint means: "T must have a compare method." The compiler checks this before generating code. No template-instantiation-error soup.
9. Pattern Matching -- Like switch, But Exhaustive¶
// Instead of: switch (value) { case 1: ... break; default: ... }
match value {
Some(v) => io.println("got " + v.to_str()),
None => io.println("nothing"),
};
// Instead of: if (state == IDLE) ... else if (state == ATTACKING) ...
match state {
AgentState.Idle => wait(),
AgentState.Patrolling(route) => follow(route),
AgentState.Attacking(target) => engage(target),
AgentState.Dead(cause) => log(cause),
};
The compiler forces you to handle every variant. Missing a case is a compile error. This eliminates an entire class of runtime bugs.
10. Async -- Like async/await, With Channels¶
use xiom.async;
// Instead of: async function fetch() { const r = await http.get(url); }
async fn fetch(url: Str) -> Result[Str, NetError] {
let response = await net.http_get(url)?;
return Ok(response.body);
}
// Instead of: new Thread(() -> { channel.send(compute()); }).start();
let (tx, rx) = Channel.bounded[Int](32);
spawn {
tx.send(expensive_computation());
};
match rx.recv() {
Ok(value) => use(value),
Err(_) => io.println("channel closed"),
};
| Other Language | XIOM |
|---|---|
async function / async fn |
async fn |
await |
await |
Promise / Future |
Future (implicit) |
C# Task / Task<T> |
Future (implicit) |
Go goroutine |
spawn |
Go channel |
Channel[T] |
11. Compile-Time Code -- comptime¶
No preprocessor. No macros. No templates. One keyword: comptime.
// Evaluated at compile time -- zero runtime cost
let size = comptime expensive_computation();
// Generics are just comptime type parameters
fn max[T: Comparable](a: T, b: T) -> T { ... }
comptime is Zig's model -- any expression can be marked compile-time. This is how generics, reflection, and specialization all work. One mechanism.
12. C FFI -- Call Any C Library¶
extern "C" {
fn malloc(size: UInt) -> *UInt8;
fn free(ptr: *UInt8);
fn printf(format: *UInt8, ...) -> Int32;
}
fn alloc(size: UInt) -> *UInt8
requires: size > 0
{
unsafe { return malloc(size); }
}
XIOM does not rewrite C libraries. It wraps them with safe interfaces and contracts. SQLite, OpenSSL, Vulkan, BLAS -- all accessed through FFI with contract-verified preconditions.
Quick Comparison Table¶
| Concept | Java/C# | C++ | Python | Rust | Go | XIOM |
|---|---|---|---|---|---|---|
| Absence | null |
nullptr |
None |
Option<T> |
nil |
Option[T] |
| Errors | exceptions | exceptions | exceptions | Result<T,E> |
if err != nil |
Result[T,E] + ? |
| Memory | GC | RAII/manual | GC | ownership+lifetimes | GC | ownership+scope |
| Classes | class |
class |
class |
no classes | no classes | type struct |
| Inheritance | extends |
: public |
(Base) |
no inheritance | no inheritance | composition only |
| Interfaces | implements |
pure virtual | ABC | impl Trait |
structural | structural |
| Generics | <T> |
template<T> |
duck | <T> |
[T] |
[T: Bound] |
| Contracts | no | no | no | no | no | requires/ensures/invariant |
| Privacy | public/private |
public:/private: |
_ convention |
pub |
capitalization | pub |
| Compile-time | annotations | templates | decorators | macros | code gen | comptime |
| Pattern match | switch (limited) |
switch (limited) |
match (3.10+) |
match |
switch |
match (exhaustive) |
| Async | async/await |
std::future |
async/await |
async/await |
goroutines | async/await + spawn |
What XIOM Does NOT Have (On Purpose)¶
| Feature | Why It's Missing |
|---|---|
| Inheritance | Composition + structural interfaces cover all use cases without the fragile base class problem. |
| Exceptions | Invisible control flow. Result[T, E] makes error paths explicit. |
| Null | Billion-dollar mistake. Option[T] with exhaustive match. |
| Lifetime annotations | Lexical scope is simpler and covers 95% of cases. |
| Function overloading | One canonical form for each function name. |
| Operator overloading | Surprising behavior at a distance. |
| Implicit conversions | What you read is what runs. |
| Default parameters | Explicitness over convenience. Use method chaining or builder pattern. |
| Macros / preprocessor | comptime covers all compile-time needs. |
| Header files | Module system replaces them. |