Might be considered a mild annoyance (due to my ignorance), but I often find myself adding new file/code to a code base, happily coding along and running Zig build and everything builds fine, only later one to realize that the new code was never being included in compilation.
Why is this the case (first language I would be working with that has this behavior), how do I understand the rationale for this from first principles? and any tips on making sure I don’t keep leaving things out of compilation without realizing? (like any compiler flag, lint check etc?)
1 Like
I think there are two main reasons for it:
-
Platform specific code, you wouldn’t want the compilation to fail just because you have code for another platform in your project. (this point also extends beyond just platform code, e.g. you might also add some build system flags that disable and break certain code paths)
-
Efficiency, it reduces the overhead of compiling and including the standard library, or other libraries. This is really important because everything in Zig is in a single compilation unit.
any tips on making sure I don’t keep leaving things out of compilation without realizing?
If you build a library then you should add testing code, so that it is compiled during testing.
And of course don’t waste time writing functions you don’t immediately need.
Other than that, I guess I can just say that you should get used to it. It really isn’t a big problem in my opinion, sure sometimes you may need to get back to the code you wrote a few hours ago and fix some small things, but is that really a big deal?
3 Likes
It’s because of Zig’s Lazy evaluation model. From my understanding Zig only evaluates code that is being referenced, think like a dependency grah. so if you want anything to be compiled it has to be evaluated in some way, the simplest approach is to include it at the root level and do something like this.
comptime {
std.testing.refAllDeclsRecursive(@import("foo.zig"));
}
This might not be optimal, because in the end this Lazy evaluation is a feature to reduce the burden of long compilation. But still you can use it if you need to.
But if you want to understand it, think of you code as a graph, if something isn’t used by something, and that thing isn’t being used or reached in some ways from main/root, it’s not going to be compiled, or at least not entirely evaluated.
8 Likes