AffineScript is a modern systems programming language that combines safety, expressiveness, and performance.
Traditional languages force a choice:
- Safe languages (Java, Python): Garbage collection, runtime checks
- Fast languages (C, C++): Manual memory, undefined behavior
AffineScript achieves both:
- Memory safe without garbage collection
- Zero-cost abstractions with predictable performance
- Compile-time verification catches bugs early
- Affine Types: Memory safety through ownership
- Dependent Types: Verify properties at compile time
- Row Polymorphism: Flexible, type-safe records
- Algebraic Effects: Controlled side effects
- WebAssembly Target: Run anywhere
fn main() -{IO}-> Unit {
println("Hello, World!")
}
Let's break this down:
fn main()- Function namedmain-{IO}->- Has IO effect (can do I/O)Unit- Returns nothingprintln(...)- Print to console
Values have exactly one owner. When the owner goes out of scope, the value is cleaned up:
fn example() {
let s = String::from("hello") // s owns the string
println(s)
} // s goes out of scope, string freed
No garbage collector needed!
Instead of copying, you can borrow:
fn print_length(s: &String) {
println("Length: " ++ show(s.len()))
}
fn main() -{IO}-> Unit {
let s = String::from("hello")
print_length(&s) // Borrow s
println(s) // Still valid!
}
The type system catches errors at compile time:
// Compile-time verified bounds checking
fn safe_index[n: Nat, T](
vec: Vec[n, T],
i: Nat where (i < n) // Index must be in bounds
) -> T {
vec[i] // Guaranteed safe!
}
Side effects are tracked in types:
// Pure function - no effects
fn add(x: Int, y: Int) -> Int {
x + y
}
// Effectful function - must declare IO
fn greet(name: String) -{IO}-> Unit {
println("Hello, " ++ name)
}
- Operating system components
- Device drivers
- Embedded systems
- WebAssembly backends
- High-performance web services
- Browser-based tools
- Trading systems
- Smart contracts
- Verified algorithms
- Numerical libraries
- Data processing
- Simulation software
Ready to learn more?
- Installation - Set up your environment
- Quick Start - Your first project
- Tour of Features - Language overview
// Vector with compile-time length
struct Vec[n: Nat, T] {
data: [T; n]
}
// Safe head - requires non-empty
fn head[n: Nat, T](vec: Vec[n + 1, T]) -> T {
vec.data[0] // Always safe - at least 1 element
}
// Append with length tracking
fn append[n: Nat, m: Nat, T](
a: Vec[n, T],
b: Vec[m, T]
) -> Vec[n + m, T] {
// Result has exactly n + m elements
Vec { data: a.data ++ b.data }
}
fn main() -{IO}-> Unit {
let v1 = Vec { data: [1, 2, 3] } // Vec[3, Int]
let v2 = Vec { data: [4, 5] } // Vec[2, Int]
let first = head(v1) // 1 (safe!)
let combined = append(v1, v2) // Vec[5, Int]
println(show(combined.data)) // [1, 2, 3, 4, 5]
}
AffineScript is designed around:
- Safety First: Memory safety, type safety, effect safety
- Predictability: No hidden costs, clear semantics
- Expressiveness: Rich types without complexity
- Practicality: Real-world systems, not just theory
Welcome to AffineScript!