# Assignment

> const by default, var only when you must mutate.

Zig has two ways to introduce a value, and the default is the immutable one.

```zig
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);
}
```

*Runnable: compiled to WebAssembly and executed by CI against Zig master. (`02-language.assignment`)*

## `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

```zig
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.
