In case I need to declare a struct in Zig I have to prefix it with a const
const Arith = struct {
x: i32,
y: i32,
fn add(self: *Arith) i32 {
return self.x + self.y;
}
};
test "struct test" {
var testArith = Arith{
.x = 9,
.y = 9,
};
expect(testArith.add() == 18);
}
But it can be initialized both ways as var
and const
so why does the type declaration need a constant keyword when it only matters whether the instance of the struct is const
or not?
Need to be const
because the order of evaluation in the root scope is undefined and because the variables of type type
only can live in the compiler (has no memory representation, the compiler is unable to produce a binary representation of it). But you can use var
inside other scopes:
comptime {
var T = struct { value: u64 };
const x: T = .{ .value = 3 };
T = struct { ok: bool };
const y: T = .{ .ok = true };
@compileLog(x.value); // <- 3
@compileLog(y.ok); // <- true
}
In the rest of the answer, I explain in detail.
const Arith = struct {...};
Creates a constant variable of a inferred type. In this case, the variable Arith
has type type
:
const Arith = struct {...};
comptime {
@compileLog(@TypeOf(Arith)); // <- type
}
This is the same as declare the variable as:
const Arith: type = struct {...};
You also can create a variable with var
Examples:
comptime {
var Arith = struct {...};
}
comptime {
var Arith: type = struct {...};
}
fn main() !void {
comptime var Arith = struct {...};
}
fn main() !void {
var Arith: type = struct {...};
}
fn main() !void {
comptime var Arith: type = struct {...};
}
Because is a variable you can modify it:
comptime {
var T = u64;
T = bool;
@compileLog(T); // <-- bool
}
There is types that can only live in the compiler, like: type
or structs that have a field of type anytype
or other comptime type.
In the case of type
, this make the compiler interpret var x: type
as comptime var x: type
.
Then, consider the following code:
var T = struct { value: u64 }; // <- Compiler error
comptime {
const x: T = .{ .value = 3 };
}
error: variable of type 'type' must be constant
because the order of evaluation in the root scope is undefined, the compiler forces to create a global variable inside the binary, but the type type
has no memory representation. So, the compiler raises an error.