Structs

Structs contain key-value pairs called fields. All keys and the types of the values must be known at compile-time.

struct Something<GenericParam> {
    val: GenericParam,

    set: fn(val: GenericParam) -> bool {
        self.val = val;
        true;
    }

}

Field modifiers

All of the following field modifiers can be used together on a single field, and the order of the modifiers does not matter.

Static fields

Sometimes you want a field to be attached to the struct itself and not an instance of the struct.

struct Person {
    name: str,

    static create: fn(name: str) -> Person {
        new Person { name };
    }

}

let me = Person::create("Google");

Hidden/Private fields

Fields that can only be accessed in the execution context of the functions inside the sctruct.

struct Person {
    name: str,
    private id: i32

    static create: fn(name: str) -> Person {
        new Person { name, id: rng() };
    }

}

let me = Person::create("Google");
me.id; // Error!

Immutable fields

Fields that cannot be mutated.

struct Person {
    const name: str,
    private id: i32

    static create: fn(name: str) -> Person {
        new Person { name, id: rng() };
    }

}

let me = Person::create("Google");
me.name = "Pedro"; // Error!

Optional fields

Fields which have a question mark (?) after the type are optional.

struct StructWithOptionalField {
    // Can either be "none", or "str"
    something: str?
}

Accessing fields

Fields are accessed using the dot notation (.).

main {
    let my_smth = new Something<str>{val: "Hello"};
    my_smth.set(val: "World");
    my_smth.val.length; // returns 5
}

Accessing optional fields

Optional fields can be accessed by the dot notation, but you must put a question mark (?) before the dot. If the optional struct is empty, then the expression returns none.

main {
    let my_struct = new StructWithOptionalField{}; // the optional field is `none`
    my_fn(my_struct.something?); // The function doesn't get executed because my_struct cannot be unwrapped
    my_struct.something = "Hello";
    my_fn(my_struct.something?); // Runs fine!
}

Keep in mind that you cannot use optional fields before you make sure they are not none.

if my_struct != none {
    // my_struct is guaranteed to not be none here, no need for question marks!
    print(my_struct.something);
}

Operator overloading

Operator overloading is done via partials.

import * from "std/ops" as Ops

struct Person {
    first_name: str
    middle_name: str
    last_name: str
}

impl Ops::Add<Person, str> for Person {

    add: fn(other: Person) -> str {
        self.first_name + " " + other.middle_name + " " + other.last_name;
    }

}

main {
    const me = new Person {first_name: "Google", middle_name: "Something", last_name: "Feud"};
    const you = new Person {first_name: "Taylor", middle_name: "Alison", last_name: "Swift"};
    print(me + you); // Google Alison Swift
}