Data Structures

Structs #

Structs define custom data types with named fields:

struct Point {
    x: f64,
    y: f64,
}

let p = Point { x: 1.0, y: 2.0 }
print(p.x)  // 1.0

Field Shorthand #

When the variable name matches the field name:

let x = 3.0
let y = 4.0
let p = Point { x, y }  // same as Point { x: x, y: y }

Default Field Values #

struct Config {
    host: str,
    port: int,
    debug: bool,
}

let cfg = Config { host: "localhost", port: 8080, debug: false }

Implementations (impl) #

Add methods to a struct:

impl Point {
    // Method that takes self
    fn distance(self) -> f64 {
        (self.x ** 2.0 + self.y ** 2.0).sqrt()
    }

    // Associated function (no self) — constructor
    fn new(x: f64, y: f64) -> Point {
        Point { x, y }
    }

    // Method with additional parameters
    fn translate(self, dx: f64, dy: f64) -> Point {
        Point { x: self.x + dx, y: self.y + dy }
    }
}

let p = Point::new(3.0, 4.0)
print(p.distance())  // 5.0

Enums #

Enums define types with named variants:

// Simple variants
enum Color {
    Red,
    Green,
    Blue,
}

// Variants with data (tuple-style)
enum Shape {
    Circle(f64),
    Rectangle(f64, f64),
}

// Variants with named fields
enum Event {
    Click { x: int, y: int },
    KeyPress(str),
    Quit,
}

Creating Enum Values #

let c = Color::Red
let s = Shape::Circle(5.0)
let e = Event::Click { x: 10, y: 20 }

Using Enums with Match #

fn area(shape: Shape) -> f64 {
    match shape {
        Shape::Circle(r) => 3.14159 * r * r,
        Shape::Rectangle(w, h) => w * h,
    }
}

Enums with Implementations #

impl Shape {
    fn describe(self) -> str {
        match self {
            Shape::Circle(r) => "Circle with radius {r}",
            Shape::Rectangle(w, h) => "Rectangle {w}x{h}",
        }
    }
}

Traits #

Traits define shared behavior (interfaces):

trait Displayable {
    fn display(self) -> str

    // Default implementation
    fn debug(self) -> str {
        "debug: {self.display()}"
    }
}

Implementing Traits #

impl Displayable for Point {
    fn display(self) -> str {
        "({self.x}, {self.y})"
    }
}

let p = Point { x: 1.0, y: 2.0 }
print(p.display())  // "(1.0, 2.0)"
print(p.debug())    // "debug: (1.0, 2.0)"

Trait Bounds (Generics) #

fn print_all(items: [T]) where T: Displayable {
    for item in items {
        print(item.display())
    }
}

Arrays #

Arrays are ordered, 0-indexed collections:

let numbers = [1, 2, 3, 4, 5]
print(numbers[0])    // 1
print(numbers[4])    // 5

// Array operations (via standard library)
numbers |> Array.push(6)
numbers |> Array.map(|x| x * 2)
numbers |> Array.filter(|x| x > 3)

See Standard Library for full Array API.

Maps #

Maps are key-value collections:

let scores = { "Alice": 95, "Bob": 87 }
print(scores["Alice"])  // 95

See Standard Library for full Map API.

Modules #

Declaring Modules #

// In math/vectors.zolo
mod math::vectors

pub struct Vec2 {
    pub x: f64,
    pub y: f64,
}

pub fn dot(a: Vec2, b: Vec2) -> f64 {
    a.x * b.x + a.y * b.y
}

Importing #

use math::vectors::{Vec2, dot}

let v = Vec2 { x: 1.0, y: 0.0 }

Visibility #

  • pub makes items visible outside the module
  • Without pub, items are module-private
enespt-br