But on the other hand, even C++ templates are Turing complete and even C++ parse trees can depend on the output of a Turing-complete evaluation. So it is hard to see what benefit a C++-like template feature is buying in comparison.
But on the other hand, even C++ templates are Turing complete and even C++ parse trees can depend on the output of a Turing-complete evaluation. So it is hard to see what benefit a C++-like template feature is buying in comparison.
One that comes to mind is Terra: http://terralang.org/
In retrospect Terra seems a clear precursor to Zig (though I don't know if it was a direct influence).
My current work on a visual programming compatible language also uses this strategy for meta programming, so I’m very familiar with the academic literature. It certainly seems that Zig got this right and is doing well implementing it in a way that is usable and understandable.
MetaML certainly does seem to be similar to Zig, although the one paper I've now read thanks to your suggestion (https://www.sciencedirect.com/science/article/pii/S030439750...) does not mention introspection and type functions, and another commenter here suggests that it is, actually, referentially opaque.
1. It is referentially transparent, i.e., unlike Lisp, i.e. nothing in the language can distinguish between `1 + 2` and `3`. This means that the semantics of the language is the same as if everything was evaluated at runtime, and the comptime annotation has no impact on semantics (assuming syntax terms aren't objects and there's no `eval`).
2. It supports type introspection and construction.
3. It doesn't have generics and typeclasses as separate constructs but as applications of comptime.
I think 3 is unique to Zig, but I wonder about 1: is it possible in MetaOCaml, as it is in Lisp, C, C++, Rust and Haskell -- but not in Zig! (or, say, Java) -- to write a unit `m`, such that m(1 + 2) is different from m(3)?
pub fn floor(x: anytype) @TypeOf(x) {
const T = @TypeOf(x);
return switch (T) {
f16 => floor16(x),
f32 => floor32(x),
f64 => floor64(x),
f128 => floor128(x),
else => @compileError("floor not implemented for " ++ @typeName(T)),
};
} template <class T> T floor(T x) { /* ... */ }
I think a documentation generator could display your Zig signature verbatim and a user could make sense of that.One alleged benefit of Java constrained genetics is that they allow in theory better error messages. Still in complex cases even after over 15 years with genetics in Java the error messages are not that great. Zig to some extend delegates to the compile-time library authors responsibility of producing good error messages. But then the error messages can be improved without waiting for the compiler to improve its reporting heuristics to cover all edge cases.