Learning Session - Nov 2025
Zig Learning Session - November 2025
Overview
An intensive hands-on Zig learning session covering core concepts through two practical projects:
- Conway’s Game of Life
- 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
selfis 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:
- Base64 decoding
- Zlib decompression
- 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.zlib→std.compress.flateArrayList.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:
trymakes it visible - Type conversions:
@intCast()required - Mutability:
*constvs*
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
- API changes in 0.15.2 - Learned to read stdlib source
- Type system precision - Understanding
*ReadervsGenericReader - Memory lifetimes - When to use stack vs heap
- Error handling flow - Chaining
trythrough operations - Unicode limitations -
u8can’t hold'█'
Aha Moments
-
“So it really is like C, grid is just a data structure” - Understanding that OOP-style syntax is pure sugar
-
“They don’t even pack function pointers in the struct?” - Realizing methods have zero runtime cost
-
“Oh it lets the compiler optimize automatically” - Grasping compile-time execution
-
“Is that just a format string?” - Recognizing patterns from other languages
-
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
- Familiar concepts - Structs, functions, pointers
- Clear mental model - What you write is what you get
- No magic - Everything is explicit and visible
- Python-like for some tasks - But with C performance
- 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)
-
comptimeprogramming - Generic data structures
- Build system deep dive
- Cross-compilation
- C interop
- Writing tests
Resources Created
- Core Concepts - Fundamental Zig concepts
- Conway’s Game of Life - First project walkthrough
- Factorio Blueprint Decoder - Detailed decompression explanation
- Quick Reference - Common patterns and gotchas
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