Zig Comptime Parameters
A comptime parameter is an argument Zig works out while the program is still compiling. Passing a type as a comptime parameter lets one function work with several types of number.
One function doubles an integer
Twice takes a type T and a value of that type. Here T is i32 and the value is 21.
const std = @import("std");
fn twice(comptime T: type, value: T) T {
return value + value;
}
pub fn main() !void {
const out = std.io.getStdOut().writer();
try out.print("{d}\n", .{twice(i32, 21)});
}The same function doubles a float
Nothing in twice changes for a new type. Only the arguments at the call change.
const std = @import("std");
fn twice(comptime T: type, value: T) T {
return value + value;
}
pub fn main() !void {
const out = std.io.getStdOut().writer();
try out.print("{d}\n", .{twice(i32, 7)});
try out.print("{d}\n", .{twice(f64, 1.5)});
}Add one to two different types
AddOne works the same way with a u8 and with an i64. Each result keeps the type that was passed in.
const std = @import("std");
fn addOne(comptime T: type, value: T) T {
return value + 1;
}
pub fn main() !void {
const out = std.io.getStdOut().writer();
try out.print("{d} {d}\n", .{ addOne(u8, 41), addOne(i64, -5) });
}Example
const std = @import("std");
fn scale(comptime T: type, value: T, factor: T) T {
return value * factor;
}
pub fn main() !void {
const out = std.io.getStdOut().writer();
try out.print("{d}\n", .{scale(i32, 6, 3)});
try out.print("{d}\n", .{scale(f64, 2.5, 4)});
}Key points
- Comptime: work Zig does at compile time, before the program runs.
- Type parameter: writing comptime T: type makes T a parameter that receives a type, such as i32 or f64.
- Value parameter: a second parameter written with the type T holds a real value of that type.
- One function, many types: the same body is checked and used for each type it is called with.
- Call: the type is passed like an ordinary argument, as in twice(i32, 21).
In this example, scale takes a type T, then a value and a factor, both of type T. The first call uses i32, so 6 times 3 gives 18. The second call uses f64, so 2.5 times 4 gives 10, printed as a whole number.
Note
the type must be known at compile time, so it can never come from a value read while the program runs.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
In `fn twice(comptime T: type, value: T) T`, what is passed for T at a call?