← Back
Logo

Mojo Programming Language

2025-07-06

#mojo #python

View on GitHub:

life.mojo
Initial Reflections on Mojo v25.5.0

A funky assortment of novel technology that feels somewhat familiar! I'm eager to see how the Modular team is able to elevate the Python language and ecosystem. Given the modern MLIR technology stack it will be interesting to see the language morph over time. Mojo appears to give me more power with expressive features like traits and more responsibility with pointers plus an ownership model. Excited to build out some smaller projects and start benchmarking the language against various Python and PyTorch implementations!

Setup (Mojo v25.5.0.dev2025062815)
Basic Syntax Notes
Integrating Python Code in a Mojo Project
Tutorial Code - Conway's Game of Life

gridv1.mojo:

            
import random

@fieldwise_init
struct Grid(Copyable, Movable, StringableRaising):
    var rows: Int
    var cols: Int
    var data: List[List[Int]]
    
    def __str__(self) -> String:
        str = String()
        for row in range(self.rows):
            for col in range(self.cols):
                if self[row, col] == 1:
                    str += "*"
                else:
                    str += " "
            if row != self.rows-1:
                str += "\n"
        return str
    
    def __getitem__(self, row: Int, col: Int) -> Int:
        return self.data[row][col]
    
    def __setitem__(mut self, row: Int, col: Int, value: Int) -> None:
        self.data[row][col] = value
    
    @staticmethod
    def random(rows: Int, cols: Int) -> Self:
        random.seed() # seed based on current time -> value is always unique
        var data: List[List[Int]] = []
        # _ follows the discard pattern. Otherwise the mojo compiler would throw a warning.
        for _ in range(rows):
            var row_data: List[Int] = []
            for _ in range(cols):
                row_data.append(Int(random.random_si64(0, 1)))
            data.append(row_data)
        return Self(rows, cols, data)

    def evolve(self) -> Self:
        next_generation = List[List[Int]]()

        for row in range(self.rows):
            row_data = List[Int]()
            # calc neighboring row indicies
            row_above = (row - 1) % self.rows
            row_below = (row + 1) % self.rows

            for col in range(self.cols):
                # calc neighboring col indicies
                col_left = (col - 1) % self.cols
                col_right = (col + 1) % self.cols
                # determine the number of populated cells
                num_neighbors = (
                    self[row_above, col_left]
                    + self[row_above, col]
                    + self[row_above, col_right]
                    + self[row, col_left]
                    + self[row, col_right]
                    + self[row_below, col_left]
                    + self[row_below, col]
                    + self[row_below, col_right]
                )

                # determine the state of current cell for next generation
                new_state = 0
                if self[row, col] == 1 and (num_neighbors == 2 or num_neighbors == 3):
                    new_state = 1
                elif self[row, col] == 0 and num_neighbors == 3:
                    new_state = 1
                row_data.append(new_state)
            next_generation.append(row_data)
        return Self(self.rows, self.cols, next_generation)                
            
        

life.mojo:

            
from gridv1 import Grid
from python import Python
import time

def run_display(
    owned grid: Grid,
    window_height: Int = 600,
    window_width: Int = 600,
    background_color: String = "black",
    cell_color: String = "green",
    pause: Float64 = 0.1,
) -> None:
    pygame = Python.import_module("pygame")
    pygame.init()

    window = pygame.display.set_mode(
        Python.tuple(window_height, window_width)
    )
    pygame.display.set_caption("Conway's Game of Life")

    cell_height = window_height / grid.rows
    cell_width = window_width / grid.cols
    border_size = 1
    cell_fill_color = pygame.Color(cell_color)
    background_fill_color = pygame.Color(background_color)

    running = True
    while running:
        event = pygame.event.poll()
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE or event.key == pygame.K_q:
                running = False
        
        window.fill(background_fill_color)
        for row in range(grid.rows):
            for col in range(grid.cols):
                if grid[row, col]:
                    x = col * cell_width + border_size
                    y = row * cell_height + border_size
                    width = cell_width - border_size
                    height = cell_height - border_size
                    pygame.draw.rect(
                        window,
                        cell_fill_color,
                        Python.tuple(x, y, width, height),
                    )
        pygame.display.flip()
        time.sleep(pause)
        grid = grid.evolve()
    pygame.quit()

def main():
    start = Grid.random(16,16)
    run_display(start)