What Zig felt like, coming from Rust | besokWhat Zig felt like, coming from Rust<br>Intro<br>I’ve spent the last 7 years as a Rust developer, working mostly on open source projects,<br>and I’d like to think I’ve built a solid feel for the language and its ecosystem along the way.<br>I gravitate toward the functional side of Rust like clean functions, expressive types, that sort of thing.<br>But I’m always curious about other languages,<br>and Zig has been on my radar for a while as a candidate C successor: lower-level,<br>lighter-weight, and steadily earning its place among the languages people take seriously.<br>I spent time with C earlier in my career, so the comparison always felt like it would be interesting to make.<br>One caveat worth stating up front: my experience with Zig begins with this project.<br>Some of the observations will look naive and obvious for the people who work with Zig on daily basis and<br>some of the decisions I made along the way were almost certainly not the optimal ones,<br>they were shaped more by habits carried over from Rust than by deep Zig idiom.<br>That’s fine, everyone has to start somewhere, and in the meantime I’m leaning on whatever cross-language intuition I’ve built up over the years, for better or worse.<br>To make the comparison fair, I decided to reimplement something I’d already built in Rust,<br>not a toy, but not a sprawling project either, and ideally something the community could actually use.<br>I settled on JSONPath: a query language for JSON, specified in RFC 9535.<br>The Rust version already existed (jsonpath-rust),<br>and the goal was to bring the same thing to Zig: zig-jsonpath.<br>IDE support<br>The first thing that caught me off guard — and honestly, who would’ve expected this to be the memorable part — was IDE support, or the near-total lack of it. I’d been using RustRover for Rust and various JetBrains flavors for other languages, and Zig, by comparison, offered little beyond syntax highlighting and basic autocompletion. It wasn’t exactly surprising, but it did force me back to basics: learning to work with the language largely from the command line. What started as a drawback turned into one of the more interesting parts of the experience. It turns out I’d simply forgotten how straightforward it can be to rely on bare CLI tooling.<br>The first real lesson here was build.zig, which handles this with surprising ease. I eventually settled on this setup:<br>zig build test # run all tests<br>zig build test -Dfilter="filter match function basic" # run one test<br>zig build test -Ddebug-query=true # all tests with debug<br>zig build compliance # compliance suite<br>zig build check # unit tests + compliance
Once you accept the terms, it’s genuinely refreshing to work with.<br>I have Zig to thank, in a roundabout way, for kicking off a bigger chain reaction, namely my move away from a full IDE toward a helix + alacritty + zellij setup.<br>Flat structure<br>With Rust, and most other languages, I’ve always spent a fair amount of time (going back and forth) trying to find the right balance<br>between file size and folder depth. You’re free to fragment files and grow the folder hierarchy as deep as you like. Zig,<br>it turned out, is fine with this too, but somehow doesn’t really encourage it (like C, which is no surprise for a low-level systems language).<br>You can nest files and folders if you want, but doing so brings a bit of import friction,<br>and the real question becomes: why bother? What do you actually gain in readability by splitting everything across more files and folders? In theory, better readability.<br>In practice, when you collapse related things into one larger file, you can just slice it and navigate section by section instead and there’s a real benefit to having everything in one place.<br>Mostly, Zig nudges you toward flat. If something needs a companion for a model, I just create a model_ file next to it and move on.<br>I don’t think this scales to large projects, meaning at some point you need a real hierarchy but the threshold for needing one turned out to be much higher in Zig than I expected.<br>In Rust, I tend to reach for folder structure early, almost by default. In Zig, I kept deferring it, and by the end of this project, I never needed it at all.<br>That contrast was useful beyond just Zig, because it made me reconsider, even in other languages,<br>whether I’m organizing files because the project genuinely needs it, or out of habit.<br>It’s also a pretty honest way to gauge how big a project actually is: if you can’t resist reaching for folders on day one,maybe it’s smaller than it feels.<br>Here’s the actual difference, side by side:<br>Rust (src/):<br>src/<br>├── lib.rs<br>├── parser.rs<br>├── parser/<br>│ ├── errors.rs<br>│ ├── macros.rs<br>│ ├── model.rs<br>│ ├── tests.rs<br>│ └── grammar/<br>│ └── json_path_9535.pest<br>├── query.rs<br>└── query/<br>├── atom.rs<br>├── comparable.rs<br>├── comparison.rs<br>├── filter.rs<br>├── jp_query.rs<br>├── queryable.rs<br>├──...