Assignment
Zig has two ways to introduce a value, and the default is the immutable one.
const std = @import("std");
const expect = std.testing.expect;
test "const and var" {
const constant: i32 = 5; // may not be reassigned
var variable: u32 = 5000; // may be reassigned
variable += 1;
// The type can be inferred from the value.
const inferred_constant = @as(i32, 5);
var inferred_variable = @as(u32, 5000);
inferred_variable += 1;
try expect(constant == 5);
try expect(variable == 5001);
try expect(inferred_constant == 5);
try expect(inferred_variable == 5001);
}
test "undefined leaves memory uninitialised" {
// `undefined` means "I will assign this before I read it". Reading it
// first is illegal behaviour, not a guaranteed zero.
var x: i32 = undefined;
x = 7;
try expect(x == 7);
}const unless proven otherwise
const is not a hint: it is enforced. Reassigning a const is a compile
error, and so is declaring a var you never mutate. That second rule surprises
people coming from C, but it means a var in Zig is a real signal: this
changes.
Type annotations are optional when the compiler can infer them. @as(i32, 5)
is an explicit cast used here to pin down what would otherwise be an untyped
comptime_int.
undefined is a promise, not a value
var x: i32 = undefined;
This says “I will write to this before I read it”. It does not mean zero.
Reading x before assigning is illegal behaviour. In a safety-enabled build
Zig fills the memory with 0xaa bytes so the mistake is loud rather than
silently plausible.