Learning Session - Nov 2025

Zig Learning Session - November 2025

Overview

An intensive hands-on Zig learning session covering core concepts through two practical projects:

  1. Conway’s Game of Life
  2. Factorio Blueprint String Decoder

Environment: Zig 0.15.2 on Linux (CachyOS)

Session Progression

Phase 1: Conway’s Game of Life

Started with a complete implementation to demonstrate core Zig concepts:

  • Struct organization and methods
  • Memory management with allocators
  • 2D grid as 1D array
  • Terminal I/O and rendering

Key insight: Methods are just namespaced functions - the struct contains only data!

Phase 2: Understanding OOP vs Zig

Deep dive into the philosophical difference:

  • Objects in OOP languages carry vtables and type information
  • Zig structs are pure data - zero runtime overhead
  • Method calls compile to direct function calls
  • self is just a convention, not a keyword

Aha moment: In disassembly, Zig looks identical to C - just data and functions.

Phase 3: Compile-time vs Runtime

Explored Zig’s superpower - seamless compile-time execution:

  • Builtins like @min() work at both compile-time and runtime
  • Compiler optimizes automatically based on what it knows
  • Same code, zero-cost abstractions

Key takeaway: You don’t need separate mechanisms for compile-time and runtime.

Phase 4: Blueprint Decoder (Hands-on)

Guided implementation of a real-world decoder:

  1. Base64 decoding
  2. Zlib decompression
  3. JSON extraction (planned)

Learning approach: More collaborative - hints and guidance rather than complete solutions.

Phase 5: API Navigation

Encountered multiple Zig 0.15.2 API changes:

  • std.compress.zlibstd.compress.flate
  • ArrayList.init(allocator)ArrayList = .{}
  • Reader/Writer buffer requirements
  • Sleep moved to std.Thread

Lesson learned: Pre-1.0 language means APIs evolve - learning to navigate docs and source code is crucial.

Phase 6: Deep Dive on Decompression

Detailed explanation of the decompression pipeline:

  • Reader interface and vtables
  • State machines and streaming
  • Window buffers and deflate algorithm
  • Memory layout of complex types

Understanding achieved: Can now reason about what Zig code compiles to and why it’s designed that way.

Key Concepts Mastered

1. Structs Are Data

// Memory layout is just the fields
const Grid = struct {
    cells: []bool,    // [ptr, len]
    width: usize,     // 8 bytes
};
// No vtable, no type info, just 24 bytes

2. Explicit Everything

  • Memory allocation: try allocator.alloc()
  • Error handling: try makes it visible
  • Type conversions: @intCast() required
  • Mutability: *const vs *

3. Defer for Cleanup

const data = try alloc();
defer free(data);  // Guaranteed cleanup

4. Error Unions

!Type  // Can be error OR Type
try expr  // Unwrap or propagate

5. Slices and Arrays

  • Arrays: [N]T - fixed size, stack
  • Slices: []T - fat pointer: [ptr, len]
  • Strings are just []const u8

6. For Loop Captures

for (items) |item| { ... }
if (optional) |value| { ... }
catch |err| { ... }

7. Format Strings

"{x:0>2}"  // Hex, zero-padded to 2

8. Builtins

@min()  @max()  @intCast()  @memset()  @memcpy()

Projects Completed

Conway’s Game of Life

Location: /home/wes/projects/game_of_zig/src/main.zig

Features:

  • 80x24 grid
  • Glider and blinker patterns
  • Terminal rendering
  • 100 generation simulation

Concepts: Memory management, 2D arrays, double buffering, I/O

Factorio Blueprint Decoder

Location: /home/wes/projects/game_of_zig/src/blueprint.zig

Successfully decoded a 50-component solar panel blueprint:

  • Stripped version byte
  • Base64 decoded (531 bytes)
  • Zlib decompressed (3987 bytes)
  • Extracted JSON

Concepts: Stream I/O, readers, decompression, dynamic buffers

Challenges Overcome

  1. API changes in 0.15.2 - Learned to read stdlib source
  2. Type system precision - Understanding *Reader vs GenericReader
  3. Memory lifetimes - When to use stack vs heap
  4. Error handling flow - Chaining try through operations
  5. Unicode limitations - u8 can’t hold '█'

Aha Moments

  1. “So it really is like C, grid is just a data structure” - Understanding that OOP-style syntax is pure sugar

  2. “They don’t even pack function pointers in the struct?” - Realizing methods have zero runtime cost

  3. “Oh it lets the compiler optimize automatically” - Grasping compile-time execution

  4. “Is that just a format string?” - Recognizing patterns from other languages

  5. Navigating API changes - Building confidence in exploring unfamiliar APIs

Comparison to Other Languages

vs Python

  • Similar: Syntax clarity, ease of use
  • Different: Explicit memory, compiled, no runtime overhead
  • Better for: CLI tools, performance-critical code, single binaries

vs C

  • Similar: Performance, memory model, predictability
  • Different: Error handling, slices, comptime, package manager
  • Better for: Everything C does, but safer and more ergonomic

vs Rust

  • Similar: Safety, zero-cost abstractions
  • Different: Simpler (no borrow checker), manual memory management, comptime
  • Trade-off: More explicit, less automatic safety

Why Zig Feels Accessible

  1. Familiar concepts - Structs, functions, pointers
  2. Clear mental model - What you write is what you get
  3. No magic - Everything is explicit and visible
  4. Python-like for some tasks - But with C performance
  5. Gradual learning curve - Don’t need to learn everything at once

Next Steps

Potential areas to explore:

  • JSON parsing (std.json)
  • More complex allocators (Arena, FixedBuffer)
  • comptime programming
  • Generic data structures
  • Build system deep dive
  • Cross-compilation
  • C interop
  • Writing tests

Resources Created

Reflection

Starting point: Familiar with reverse engineering (Ghidra), some C knowledge, lots of Python

Ending point: Can read and write Zig, understand memory layout, navigate stdlib, debug API issues

Key achievement: Understanding that Zig’s power comes from removing abstraction layers rather than adding them. The “OOP-style” syntax is just sugar over simple, predictable code.

Most valuable skill learned: Reading stdlib source code to understand APIs. In a pre-1.0 language with evolving APIs, this is essential.

Quotes from the Session

“this is very neat, it already feels way more accessible than trying to use C to do anything”

“ohhhh so it really is like C, grid is just a data structure and we have convenient shorthands that feel like OOP”

“wait a second they don’t even pack function pointers to those functions in the struct?”

“wow this is very neat, it already feels way more accessible than trying to use C”

“very cool, glad I asked” (about compile-time vs runtime)

Final Thoughts

Zig delivers on its promise: a better C. The learning curve isn’t about learning complexity, it’s about unlearning OOP assumptions. Once you realize that structs are just data and methods are just functions, everything clicks into place.

The reverse engineering background was surprisingly helpful - thinking about memory layout and what code compiles to makes Zig’s design decisions obvious.

Next session should focus on more advanced features (comptime, generics) or building a more substantial project that ties everything together.


Session Date: November 30, 2025 Duration: ~2-3 hours Projects: 2 complete implementations Lines of code written: ~200 Bugs debugged: Many (all API-related!) Aha moments: Numerous

Wesley Ray · blog · git · resume