Assignment in zig has this syntax: (const|var) identifier[: type] = value
Type
The type
may be ommitted if the data of value
can be inferred.
const constant: i32 = 5;
var variable: u32 = 5000;
// @as performs an explicit type coercion
const inferred_constant = @as(i32, 5);
var inferred_variable = @as(u32, 5000);
Constants AND variables must have a value. The value undefined
, which
coerces to any type, may be used as long as a type annotation is provided.
const a: i32 = undefined;
var b: u32 = undefined;
Like many other languages you should use const
over var
to follow the
principal of immutability.
Inference
This is a pretty standard way to create a struct. It uses type inference:
const user = User{
.power = 9001,
.name = "Goku",
};
Without type inference it's a bit less readable:
const user: User = User{
.power = 9001,
.name = "Goku",
};
Technically, you can also reverse the inference:
const user: User = .{
.power = 9001,
.name = "Goku",
};
This third method is sometimes used when returning a struct from a function:
pub fn init(name: []const u8, power: u64) User {
// instead of return User{...}
return .{
.name = name,
.power = power,
};
}
Comptime
The std.debug.print
function's string formatting is a comptime string.
pub fn print(comptime fmt: []const u8, args: anytype) void {
One common issue is with comptime_int
and comptime_float
which are both
respectively the default values when an integer/float's type is inferred. As a
result writing var i = 0;
is invalid and will print:
variable of type 'comptime_int' must be const or comptime.
You can of course use const or just assign a type to fix it:
var i: usize = 0;
var j: f64 = 0;
Perhaps not the best default, but who knows maybe with time I'll change my mind about that.
anytype
pub fn print(comptime fmt: []const u8, args: anytype) void {
Anytype in zig is a little different from go's interface{}
or c'c
void*
. Instead of runtime switching on the type, zig will create copies of the
function at compile-time for each type we pass to it.