Getting Started Series
Follow these tutorials in order to build a solid foundation in Simplex, from basic syntax to building complete AI-powered applications.
Hello World
Write and run your first Simplex program. Learn variables, functions, and basic syntax.
2Working with Types
Master structs, enums, pattern matching, and Simplex's powerful type system.
3Actors & Messages
Learn the actor model for building concurrent, distributed, fault-tolerant systems.
4AI-Enhanced Pipeline
Integrate AI into your data processing with type-safe extraction and classification.
5Building a CHAI Hive
Create a complete Cognitive Hive with specialized AI workers and intelligent routing.
Start from the Beginning
New to Simplex? Start with Tutorial 1: Hello World and work through each tutorial in order. Each builds on concepts from the previous one.
Quick Tutorials
Variables and Types
Simplex uses let for immutable bindings and var for mutable ones:
// Immutable - preferred default
let name = "Simplex" // Type inferred as String
let version: i64 = 1 // Explicit type annotation
// Mutable - when you need to change values
var count = 0
count += 1 // OK: count is mutable
// Basic types
let integer: i64 = 42
let float: f64 = 3.14
let boolean: Bool = true
let text: String = "Hello"
// Collections
let list = [1, 2, 3] // List<i64>
let map = {"key": "value"} // Map<String, String>
let tuple = (1, "two", 3.0) // (i64, String, f64)
Functions
Functions are defined with fn. Return types are inferred or explicit:
// Basic function
fn greet(name: String) -> String {
"Hello, {name}!" // Last expression is returned
}
// Generic function
fn first<T>(items: List<T>) -> Option<T> {
if items.is_empty() {
None
} else {
Some(items[0])
}
}
// Closures
let double = x => x * 2
let numbers = [1, 2, 3].map(x => x * 2) // [2, 4, 6]
// Higher-order functions
fn apply_twice(f: fn(i64) -> i64, x: i64) -> i64 {
f(f(x))
}
let result = apply_twice(double, 5) // 20
Pattern Matching
Pattern matching is powerful and expressive in Simplex:
// Match on enums
enum Shape {
Circle(radius: f64),
Rectangle(width: f64, height: f64),
Triangle(base: f64, height: f64)
}
fn area(shape: Shape) -> f64 {
match shape {
Shape::Circle(r) => 3.14159 * r * r,
Shape::Rectangle(w, h) => w * h,
Shape::Triangle(b, h) => 0.5 * b * h
}
}
// Match with guards
fn describe(n: i64) -> String {
match n {
0 => "zero",
n if n < 0 => "negative",
n if n > 100 => "large",
_ => "positive"
}
}
// Destructuring
let (x, y) = get_point()
let User { name, email, .. } = get_user()
Actors
Actors are the core concurrency primitive in Simplex:
actor BankAccount {
var balance: f64 = 0.0
// Fire-and-forget message
receive Deposit(amount: f64) {
balance += amount
checkpoint() // Persist state
}
// Request-response message
receive Withdraw(amount: f64) -> Result<f64, Error> {
if amount > balance {
return Err(Error("Insufficient funds"))
}
balance -= amount
checkpoint()
Ok(balance)
}
receive GetBalance -> f64 {
balance
}
}
// Using the actor
fn main() {
let account = spawn BankAccount
send(account, Deposit(100.0)) // Fire-and-forget
let balance = ask(account, GetBalance) // Request-response
print("Balance: {balance}")
}
AI Integration
AI operations are first-class citizens in Simplex:
fn process_document(doc: String) {
// Text completion
let summary = await ai::complete(
"Summarize this document: {doc}"
)
// Generate embedding
let embedding = ai::embed(doc)
// Structured extraction
struct Metadata {
title: String,
author: Option<String>,
date: Option<Date>,
topics: List<String>
}
let metadata = await ai::extract<Metadata>(doc)
// Classification
enum Category { Technical, Business, Legal, Personal }
let category = await ai::classify<Category>(doc)
// Parallel AI operations
let (sum, ents, sent) = await parallel(
ai::complete("Summarize: {doc}"),
ai::extract<List<Entity>>("Extract entities: {doc}"),
ai::classify<Sentiment>(doc)
)
}