Mojo Modules and Packages

A module is a single .mojo file that contains functions, structs, and constants you want to reuse across multiple programs. A package is a folder of related modules. Organizing code into modules and packages makes large projects manageable and allows you to share libraries with others.

The City District Analogy

  Project (the city)
  └── package: math_utils/ (a district)
      ├── module: vectors.mojo  (one street)
      ├── module: matrices.mojo (another street)
      └── module: stats.mojo    (another street)

  Each street handles one set of related topics.
  You travel to the street you need when you need it.
  No need to understand every street to use one.

Creating a Module

Any .mojo file is a module. Functions, structs, and aliases defined at the top level of the file are the module's public interface.

# File: geometry.mojo

fn circle_area(radius: Float64) -> Float64:
    return 3.14159265 * radius * radius

fn rectangle_area(width: Float64, height: Float64) -> Float64:
    return width * height

fn triangle_area(base: Float64, height: Float64) -> Float64:
    return 0.5 * base * height

struct Point:
    var x: Float64
    var y: Float64

    fn __init__(inout self, x: Float64, y: Float64):
        self.x = x
        self.y = y

    fn distance_to(self, other: Point) -> Float64:
        var dx = self.x - other.x
        var dy = self.y - other.y
        return (dx * dx + dy * dy) ** 0.5

Importing from a Module

# File: main.mojo (in the same folder as geometry.mojo)

from geometry import circle_area, rectangle_area, Point

fn main():
    print(circle_area(5.0))            # 78.53...
    print(rectangle_area(4.0, 6.0))   # 24.0

    var p1 = Point(0.0, 0.0)
    var p2 = Point(3.0, 4.0)
    print(p1.distance_to(p2))         # 5.0

Import Everything from a Module

from geometry import *   # imports all public names

Import the Module Itself

import geometry

fn main():
    print(geometry.circle_area(3.0))   # access via module name

Creating a Package

A package is a directory containing a special file called __init__.mojo. This file marks the directory as a package and can re-export names from sub-modules for convenience.

Project structure:
  my_project/
  ├── main.mojo
  └── math_utils/
      ├── __init__.mojo
      ├── vectors.mojo
      ├── matrices.mojo
      └── stats.mojo
# File: math_utils/vectors.mojo

struct Vector3D:
    var x: Float64
    var y: Float64
    var z: Float64

    fn __init__(inout self, x: Float64, y: Float64, z: Float64):
        self.x = x
        self.y = y
        self.z = z

    fn magnitude(self) -> Float64:
        return (self.x**2 + self.y**2 + self.z**2) ** 0.5

    fn dot(self, other: Self) -> Float64:
        return self.x*other.x + self.y*other.y + self.z*other.z
# File: math_utils/__init__.mojo
from .vectors import Vector3D
from .matrices import Matrix2x2
from .stats import mean, std_dev
# File: main.mojo
from math_utils import Vector3D

fn main():
    var v1 = Vector3D(1.0, 0.0, 0.0)
    var v2 = Vector3D(0.0, 1.0, 0.0)
    print(v1.dot(v2))        # 0.0 — perpendicular vectors
    print(v1.magnitude())    # 1.0

Standard Library Modules

Module                | Contents
----------------------|----------------------------------------------
memory                | UnsafePointer, memcpy, memset
algorithm             | vectorize, parallelize, tile, sort
collections           | List, Dict, Set, Optional
testing               | assert_true, assert_equal, Bench
sys                   | argv, exit, info (OS and hardware queries)
math                  | sqrt, sin, cos, exp, log, pi, e
time                  | now(), sleep(), PerfCounter
python                | Python, PythonObject
io                    | print, FileHandle

Selective Imports for Clarity

Import only what you need. Selective imports make it clear where each name comes from when reading the code later.

# Selective — preferred for readability
from collections import List, Dict
from algorithm import vectorize
from math import sqrt, pi

# Wildcard — convenient but hides origins
from math import *   # where does sqrt come from? unclear

fn main():
    var nums = List[Float64]()
    var result = sqrt(25.0)   # with wildcard: hard to trace
    print(result)

Module Visibility

All top-level definitions in a Mojo module are public by default. Future versions of Mojo will introduce access modifiers to mark definitions as private, but today everything at module scope is accessible to importers.

Key Takeaways

A module is a single .mojo file. A package is a directory with an __init__.mojo file. Import specific names with from module import name or the whole module with import module. Packages group related modules under one namespace. The __init__.mojo file controls what names a package exposes to importers. Prefer selective imports over wildcards to keep the origin of each name clear. All top-level definitions are currently public in Mojo modules.

Leave a Comment

Your email address will not be published. Required fields are marked *