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.
