For the following Zig code:
pub fn Box(comptime N: usize) type {
@compileLog(N);
if (N > 100) {
return struct {
pub const K = u32;
};
} else {
return struct {
pub const M = f64;
};
}
}
test "Box" {
const A = Box(10);
const B = Box(200);
const C = Box(50);
const D = Box(10);
@compileLog(A);
@compileLog(B);
@compileLog(C);
@compileLog(D);
@compileLog(A == B);
@compileLog(A == C);
@compileLog(B == C);
}
I have received the output:
1.zig:2:5: error: found compile log statement
@compileLog(N);
^~~~~~~~~~~~~~
Compile Log Output:
@as(usize, 10)
@as(usize, 200)
@as(usize, 50)
@as(type, 1.Box(10))
@as(type, 1.Box(200))
@as(type, 1.Box(10))
@as(type, 1.Box(10))
@as(bool, false)
@as(bool, true)
@as(bool, false)
What is Zig’s caching strategy for generic functions that I am curious about?
The caching for the function call is the argument values, you can see that with the compile log in the function.
And user defined/generic type equivalence is based on 1) the source location and 2) the comptime values it captures.
Which you can see with your other compile logs and type comparisons.
I think whether it is cached depends on the inside of struct{...}, specifically whether this parameter is involved in the computation in any form.
For example, the result of this Box2 is quite different, because N enters inside struct{...}, even though N has no substantial effect on the result.
.
pub fn Box2(comptime N: usize) type {
@compileLog(N);
if (N > 100) {
return struct {
pub const K = u32;
pub const v: usize = 0 + N - N;
};
} else {
return struct {
pub const M = f64;
pub const v: usize = 0 + N - N;
};
}
}
test "Box2" {
const A = Box2(10);
const B = Box2(200);
const C = Box2(50);
const D = Box2(10);
@compileLog(A);
@compileLog(B);
@compileLog(C);
@compileLog(D);
@compileLog(A == B);
@compileLog(A == C);
@compileLog(B == C);
}
Compile Log Output:
@as(usize, 10)
@as(usize, 200)
@as(usize, 50)
@as(type, 1.Box2(10))
@as(type, 1.Box2(200))
@as(type, 1.Box2(50))
@as(type, 1.Box2(10))
@as(bool, false)
@as(bool, false)
@as(bool, false)
1 Like