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