Playing Super Mario Bros. 3 Through Nix Attribute Paths
Nix’s lazy evaluation means an attribute path isn’t just a lookup into a catalogue — it’s a program the evaluator walks, generating each node only when something asks for it. That property lets attribute sets recurse infinitely and still terminate: indexing three levels deep costs exactly three evaluations and never builds the rest of the tree. Developer Farid Zakaria pushed the idea to its logical extreme by making the attribute path a sequence of NES controller inputs, so that a call like nix build '.#level1.rightb.rightb.rightab' walks a lazily-generated tree of game frames and emits the exact PNG you’d see after pressing those buttons on real hardware.
The clever part is what the Nix store becomes: a persistence layer for a reproducible state machine. Every frame is its own derivation that takes the previous frame’s savestate as input, so branching off the middle of a hundred-press run costs a single press, and appending to the end costs one too — ancestor frames are never re-emulated. Because the dependency graph mirrors the input sequence, you can query the store backwards to recover which buttons produced a given frame, and stitching a full video (.play) emulates nothing at all — it’s just a directory of symlinks handed to ffmpeg.
The experiment doubles as a tour of Nix’s real limits. Evaluation costs about 0.7ms per press and linearly hits a stack overflow around 2,400 presses, liftable to 20,000 by raising max-call-depth; past that the Linux 131,072-byte per-argument cap (MAX_ARG_STRLEN) forces feeding the run from a file instead, which produces byte-identical store paths. The takeaway is conceptual: nothing about Nixpkgs requires the tree to be a package catalogue. Laziness plus content-addressed storage make a package manager a surprisingly reasonable engine for reproducible state machines — even ones that play Mario.
Read the full article
Continue reading at Hacker News →This is an AI-generated summary. Read the original for the full story.