ESC
Type to search...
S
Soli Docs

Modules

module MyModule
    def hello
        println("Hello from MyModule!")
    end
end

Import a module.

import MyModule from "./my_module.sl"

MyModule.hello()

Import specific members.

import { hello } from "./my_module.sl"

hello()

Organize code with exports, imports, classes, and module structure.

Export Declarations

export

Makes a function, class, or constant available to other modules.

# math.sl

# Private function (not exported)
def validate_number(n: Int) -> Bool
    n >= 0
end

# Exported functions
export def add(a: Int, b: Int) -> Int
    a + b
end

export def subtract(a: Int, b: Int) -> Int
    a - b
end

export def multiply(a: Int, b: Int) -> Int
    a * b
end

export def divide(a: Int, b: Int) -> Float
    if (b == 0)
        panic("Division by zero")
    end
    float(a) / float(b)
end

export def factorial(n: Int) -> Int
    if (n <= 1)
        return 1
    end
    n * factorial(n - 1)
end
Classes in Modules

Modules can contain classes, enabling organized domain-driven code structures.

# models.sl

# Private helper class (not exported)
class ValidationResult
    is_valid: Bool;
    errors: String[];

    new
        this.is_valid = true;
        this.errors = [];
    end

    def add_error(msg: String)
        this.is_valid = false;
        this.errors.push(msg);
    end
end

# Exported classes
export class User
    id: Int;
    username: String;
    email: String;

    new(id: Int, username: String, email: String)
        this.id = id;
        this.username = username;
        this.email = email;
    end

    def get_display_name -> String
        this.username + " (" + this.email + ")"
    end
end

export class Post
    id: Int;
    title: String;
    content: String;
    author: User;

    new(id: Int, title: String, content: String, author: User)
        this.id = id;
        this.title = title;
        this.content = content;
        this.author = author;
    end

    def get_summary -> String
        let preview = this.content.slice(0, 100);
        this.title + " by " + this.author.username
    end
end
Nested Classes in Modules

Modules can also contain nested classes using the :: pattern for domain organization.

# controllers.sl

export class Posts
    class Action
        def create(title: String, content: String) -> Post
            # Create a new post
            new Post(0, title, content, current_user())
        end

        def update(id: Int, updates: Any) -> Post?
            # Update an existing post
            find_post_by_id(id).update(updates)
        end

        def delete(id: Int) -> Bool
            # Delete a post
            remove_post(id)
        end
    end

    class View
        def list(page: Int, per_page: Int) -> Post[]
            paginated_posts(page, per_page)
        end

        def show(id: Int) -> Post?
            find_post_by_id(id)
        end
    end
end

export class Users
    class Action
        def register(username: String, email: String) -> User
            new User(0, username, email)
        end

        def login(email: String, password: String) -> User?
            authenticate_user(email, password)
        end
    end

    class Validator
        def validate_registration(data: Any) -> Bool
            data["username"] != null && data["email"] != null
        end
    end
end
Importing Classes

Import classes from modules using named imports or module namespace.

# Import classes by name
import { User, Post } from "./models.sl";

let user = new User(1, "alice", "[email protected]");
let post = new Post(1, "Hello World", "Content here", user);

# Import with namespace
import "./controllers.sl" as controllers;

let action = new controllers.Posts.Action();
action.create("My Post", "Post content");

# Import nested classes directly
import { Posts::Action, Posts::View } from "./controllers.sl";

let view = new Posts::View();
let posts = view.list(1, 10);

Import Statements

import

Import functions and classes from other modules.

# Import all exports
import "./math.sl";
print(add(2, 3));        # 5
print(factorial(5));     # 120

# Named imports
import { add, multiply } from "./math.sl";
let sum = add(1, 2);          # 3
let product = multiply(3, 4); # 12

# Aliased imports
import { add as sum, multiply as times } from "./math.sl";
let result = sum(10, 20);  # 30
let doubled = times(5, 6); # 30

# Import everything with a namespace
import "./utils.sl" as utils;
let formatted = utils.format_date(DateTime.utc());

Project Structure

my-project/
├── soli.toml
├── src/
│   ├── main.sl
│   ├── config.sl
│   └── utils/
│       ├── mod.sl
│       ├── string.sl
│       ├── array.sl
│       └── datetime.sl
└── lib/
    └── math/
        ├── mod.sl
        ├── basic.sl
        └── advanced.sl

Package Configuration

[package]
name = "my-app"
version = "1.0.0"
description = "My awesome soli application"
main = "src/main.sl"

[dependencies]
# Local dependency
utils = { path = "./lib/utils" }

[dev-dependencies]
test-utils = { path = "./tests/test-utils" }

[scripts]
dev = "soli serve"
build = "soli build --release"
test = "soli test"

Use Keyword

use

Alternative syntax for importing (alias for import).

use "./math.sl";
use { add, multiply } from "./math.sl";
use "./utils.sl" as utils;