This Article IsCreated at 2023-11-11Last Modified at 2023-11-11Referenced as ia.www.f10

The Experience of Programming in Zig

Recently, I ported minikanren to Zig. While I did make the Zig compiler crash twice, the porting process is straight-forward. I think the code I wrote was pretty much bug-free too. When writing tests, I had a single bug, of which a function returned pointer to its stack frame (tha data was invalid when used).

With the amount of defer and try used, I couldn’t have made it in C without omitting error handling. In fact, I never enjoyed programming in C.

When expressing my will, Zig only gives me bit of resistance. That’s why I keep using it to write code.

The code (kanren.zig) can be easily ported to Rust, but I probably wouldn’t have made it Rust either. When I coded in Rust, I often find myself fighting with the borrow checker, the type system (no dependent type), and the syntax (why ::<>). Fighting the borrow checker is ok, since I understand its rules. Fighting the syntax is nuisance, since it is unambiguous what I mean with foo<T>(). Fighting with the type system is… I really hate it. It’s not just the lack of dependent types. The type system breaks inside the Hindley-Milner framework because of the type checker, and other compiler “bugs” like “not be able to mix async and generic” (I think it is fixed now). I hate it I hate it. scream in pain

As a final thought, I hope Zig’s async/await feature gets added back soon. It is essentially ucontext/setjmp at language level while being more convenient to use. For the mean time, checkout minicoro or zigcoro