Primitive Types

Simplex provides several built-in primitive types:

Type Description Example
i64 64-bit signed integer 42, -100
f64 64-bit floating point 3.14, -0.5
bool Boolean true, false
String UTF-8 text "hello"
char Unicode character 'a', '@'

Structs

Structs let you group related data together:

structs.sx
struct Person {
    name: String,
    age: i64,
    email: String
}

fn main() {
    // Create an instance
    let alice = Person {
        name: "Alice",
        age: 30,
        email: "alice@example.com"
    }

    print("{alice.name} is {alice.age} years old")
}

Methods on Structs

You can add methods to structs:

methods.sx
struct Rectangle {
    width: f64,
    height: f64
}

impl Rectangle {
    // Constructor
    fn new(width: f64, height: f64) -> Self {
        Rectangle { width, height }
    }

    // Method using self
    fn area(self) -> f64 {
        self.width * self.height
    }

    fn perimeter(self) -> f64 {
        2.0 * (self.width + self.height)
    }
}

fn main() {
    let rect = Rectangle::new(10.0, 5.0)
    print("Area: {rect.area()}")
}

Enums

Enums define a type by enumerating its possible variants:

enums.sx
enum Status {
    Pending,
    Processing,
    Completed,
    Failed(String)  // Variant with data
}

fn describe_status(status: Status) -> String {
    match status {
        Status::Pending => "Waiting to start",
        Status::Processing => "In progress",
        Status::Completed => "All done!",
        Status::Failed(reason) => "Failed: {reason}"
    }
}

fn main() {
    let status = Status::Failed("Connection timeout")
    print(describe_status(status))
}

Option and Result

Two essential built-in enums for handling absence and errors:

option-result.sx
// Option: A value that might not exist
fn find_user(id: i64) -> Option<String> {
    if id == 1 {
        Some("Alice")
    } else {
        None
    }
}

// Result: An operation that might fail
fn divide(a: f64, b: f64) -> Result<f64, String> {
    if b == 0.0 {
        Err("Cannot divide by zero")
    } else {
        Ok(a / b)
    }
}

fn main() {
    // Handling Option
    match find_user(1) {
        Some(name) => print("Found: {name}"),
        None => print("User not found")
    }

    // Handling Result with ? operator
    let result = divide(10.0, 2.0)?
    print("Result: {result}")
}

The ? Operator

The ? operator automatically propagates errors. If a Result is Err, it returns early from the function. This makes error handling concise and readable.

Pattern Matching

Pattern matching is a powerful way to destructure and inspect values:

patterns.sx
struct Point { x: f64, y: f64 }

fn describe_point(p: Point) -> String {
    match p {
        Point { x: 0.0, y: 0.0 } => "Origin",
        Point { x: 0.0, y } => "On Y-axis at {y}",
        Point { x, y: 0.0 } => "On X-axis at {x}",
        Point { x, y } if x == y => "On diagonal at {x}",
        Point { x, y } => "At ({x}, {y})"
    }
}

fn main() {
    print(describe_point(Point { x: 0.0, y: 5.0 }))
    print(describe_point(Point { x: 3.0, y: 3.0 }))
}

Generics

Write functions and types that work with any type:

generics.sx
// Generic struct
struct Pair<T> {
    first: T,
    second: T
}

// Generic function
fn swap<T>(pair: Pair<T>) -> Pair<T> {
    Pair {
        first: pair.second,
        second: pair.first
    }
}

fn main() {
    let numbers = Pair { first: 1, second: 2 }
    let swapped = swap(numbers)
    print("{swapped.first}, {swapped.second}")  // 2, 1

    let strings = Pair { first: "hello", second: "world" }
    let swapped = swap(strings)
    print("{swapped.first}, {swapped.second}")  // world, hello
}

Try It Yourself

Create an enum called Shape with variants for Circle(radius), Rectangle(width, height), and Triangle(base, height). Write a function that calculates the area for each shape using pattern matching.

Summary

In this tutorial, you learned:

  • Primitive types in Simplex
  • Creating structs and adding methods with impl
  • Defining enums with variants that can hold data
  • Using Option and Result for safe handling
  • Pattern matching with match expressions
  • Writing generic functions and types

In the next tutorial, we'll explore Simplex's actor model for building concurrent and distributed systems.