I’m trying to understand better how comptime works. For that, I’m trying to write a function that returns an array of bytes.
The signature I want is the following:
fn range(comptime start: comptime_int, comptime end: comptime_int) [end - start]u8
The behavior I want that when i call range, like this:
const v = range(1, 6);
I get:
const v = [5]u8{1, 2, 3, 4, 5};
The key point is that I want to force the compiler to always evaluate my function at compile time. I want it to act as a macro.
I came up with the following:
pub inline fn range(comptime start: comptime_int, comptime end: comptime_int) [end - start]u8 {
return comptime blk: {
var array: [end - start]u8 = undefined;
for (&array, start..end) |*item, n|
item.* = n;
break :blk array;
};
}
First I put all the logic in a comptime block, to force the compile time execution. So, If I evaluate the function with parameters start = 1 and end = 6, it should be equivalent to the following:
fn range(comptime start: comptime_int, comptime end: comptime_int) [end - start]u8 {
return [5]u8{1, 2, 3, 4, 5};
}
I also added the inline keyword to force the function to be semantically inlined. With that I intend that when the compiler sees:
range(1, 6)
It actually replaces it with:
[5]u8{1, 2, 3, 4, 5}
.
Am I right? Is there a simpler way to achieve what I want?
I know that I could write the function without the inline keyword and the comptime block, and then evaluate it like this:
const v = comptime range(1, 6);
This would simplify my function definition, but I would have to always prepend the function evaluation with the comptime keyword.
This is not what I want, I want my function to act just as a macro, so If I want an array having the values 1 … 21, I don’t have to write it by hand. But I want to explicitly force comptime evaluation.