Obviously, we should not compare small personal project languages with decades-old industry languages by factors determined by the sheer amount of work thrown in. We compare them mostly by fundamental design principles.
In this case, partial evaluation is a massively more principled and efficient way of doing metaprogramming than preprocessing or macros. There are limitations compared to Lisp-style unrestricted untyped metaprogramming, but not any that I would much miss in practice.
With partial evaluation, we automatically get type and scope safety, and also only need one language instead of several. Optimizations also cascade in a principled way: we can compile code-generating code to fast machine code, which we then use to generate faster code or generate it faster, but the then-resulting code can be also used to generate code, and so on.
At the same time, Zig is basically only a thin layer on top of LLVM. Since it's a low-level language itself, it can get away with having close to no static flow analysis beyond this partial evaluation (and maybe types?)
In this case, partial evaluation is a massively more principled and efficient way of doing metaprogramming than preprocessing or macros. There are limitations compared to Lisp-style unrestricted untyped metaprogramming, but not any that I would much miss in practice.
With partial evaluation, we automatically get type and scope safety, and also only need one language instead of several. Optimizations also cascade in a principled way: we can compile code-generating code to fast machine code, which we then use to generate faster code or generate it faster, but the then-resulting code can be also used to generate code, and so on.