# Appendix B. Zig Cheat Sheet

## Appendix B. Zig Cheat Sheet

### B.1 Basic Program

```zig
const std = @import("std");

pub fn main() void {
    std.debug.print("Hello, Zig!\n", .{});
}
```

`main` is where the program starts. `std` is the standard library. `std.debug.print` prints formatted text.

### B.2 Build and Run

```bash
zig run main.zig
```

Compile and run one file.

```bash
zig build-exe main.zig
```

Compile one file into an executable.

```bash
zig test main.zig
```

Run tests in one file.

```bash
zig build
```

Run the project build script.

### B.3 Constants and Variables

```zig
const x = 10;
var y = 20;
```

Use `const` when the value does not change. Use `var` when the value changes.

```zig
var count: i32 = 0;
count += 1;
```

You can write the type explicitly after `:`.

### B.4 Common Types

```zig
const a: i32 = -10;
const b: u32 = 10;
const c: f64 = 3.14;
const ok: bool = true;
const ch: u8 = 'A';
```

Common integer types:

| Type | Meaning |
|---|---|
| `i8`, `i16`, `i32`, `i64` | Signed integers |
| `u8`, `u16`, `u32`, `u64` | Unsigned integers |
| `usize` | Size/index type |
| `isize` | Signed pointer-sized integer |

### B.5 Arrays and Slices

```zig
const nums = [_]i32{ 1, 2, 3 };
```

This is a fixed array.

```zig
const first = nums[0];
```

Indexing starts at `0`.

```zig
const part = nums[0..2];
```

This creates a slice containing items at indexes `0` and `1`.

Array type:

```zig
[3]i32
```

Slice type:

```zig
[]const i32
```

### B.6 Strings

```zig
const name = "Zig";
```

A string literal is a slice of bytes.

```zig
const text: []const u8 = "hello";
```

Zig strings are usually UTF-8 bytes. Zig does not hide text encoding from you.

### B.7 If

```zig
if (x > 0) {
    std.debug.print("positive\n", .{});
} else {
    std.debug.print("not positive\n", .{});
}
```

`if` can also produce a value:

```zig
const sign = if (x >= 0) 1 else -1;
```

### B.8 Switch

```zig
const result = switch (value) {
    0 => "zero",
    1 => "one",
    else => "many",
};
```

`switch` must handle all possible cases, or it must include `else`.

### B.9 While Loop

```zig
var i: usize = 0;

while (i < 5) : (i += 1) {
    std.debug.print("{}\n", .{i});
}
```

The expression after `:` runs after each loop iteration.

### B.10 For Loop

```zig
const nums = [_]i32{ 10, 20, 30 };

for (nums) |n| {
    std.debug.print("{}\n", .{n});
}
```

With index:

```zig
for (nums, 0..) |n, i| {
    std.debug.print("{}: {}\n", .{ i, n });
}
```

### B.11 Functions

```zig
fn add(a: i32, b: i32) i32 {
    return a + b;
}
```

Call it:

```zig
const x = add(2, 3);
```

A function that returns nothing uses `void`:

```zig
fn sayHello() void {
    std.debug.print("hello\n", .{});
}
```

### B.12 Errors

```zig
const MyError = error{
    NotFound,
    InvalidInput,
};
```

A function that can fail:

```zig
fn load() MyError!void {
    return MyError.NotFound;
}
```

Use `try` to propagate the error:

```zig
try load();
```

Use `catch` to handle it:

```zig
load() catch |err| {
    std.debug.print("error: {}\n", .{err});
};
```

### B.13 Optionals

```zig
var maybe_number: ?i32 = null;
```

An optional value is either a value or `null`.

```zig
maybe_number = 42;
```

Unwrap with `if`:

```zig
if (maybe_number) |n| {
    std.debug.print("{}\n", .{n});
}
```

### B.14 Pointers

```zig
var x: i32 = 10;
const p: *i32 = &x;
```

`&x` means “address of x.”

```zig
p.* = 20;
```

`p.*` means “the value pointed to by p.”

### B.15 Structs

```zig
const Point = struct {
    x: i32,
    y: i32,
};
```

Create a value:

```zig
const p = Point{
    .x = 10,
    .y = 20,
};
```

Access fields:

```zig
std.debug.print("{} {}\n", .{ p.x, p.y });
```

### B.16 Methods

```zig
const Point = struct {
    x: i32,
    y: i32,

    fn lengthSquared(self: Point) i32 {
        return self.x * self.x + self.y * self.y;
    }
};
```

Call it:

```zig
const n = p.lengthSquared();
```

### B.17 Enums

```zig
const Direction = enum {
    north,
    south,
    east,
    west,
};
```

Use with `switch`:

```zig
switch (dir) {
    .north => {},
    .south => {},
    .east => {},
    .west => {},
}
```

### B.18 Unions

```zig
const Value = union(enum) {
    int: i32,
    float: f64,
    text: []const u8,
};
```

Use with `switch`:

```zig
switch (value) {
    .int => |n| std.debug.print("{}\n", .{n}),
    .float => |f| std.debug.print("{}\n", .{f}),
    .text => |s| std.debug.print("{s}\n", .{s}),
}
```

### B.19 Defer

```zig
const file = try std.fs.cwd().openFile("data.txt", .{});
defer file.close();
```

`defer` runs at the end of the current scope.

Use it for cleanup.

### B.20 Allocators

```zig
const allocator = std.heap.page_allocator;
```

Allocate memory:

```zig
const buffer = try allocator.alloc(u8, 1024);
defer allocator.free(buffer);
```

Many Zig APIs ask for an allocator explicitly.

### B.21 ArrayList

```zig
var list = std.ArrayList(i32).init(allocator);
defer list.deinit();

try list.append(10);
try list.append(20);
```

Read items:

```zig
for (list.items) |item| {
    std.debug.print("{}\n", .{item});
}
```

### B.22 HashMap

```zig
var map = std.StringHashMap(i32).init(allocator);
defer map.deinit();

try map.put("one", 1);
try map.put("two", 2);
```

Get a value:

```zig
if (map.get("one")) |value| {
    std.debug.print("{}\n", .{value});
}
```

### B.23 Comptime

```zig
fn identity(comptime T: type, value: T) T {
    return value;
}
```

Use it:

```zig
const a = identity(i32, 10);
const b = identity([]const u8, "hello");
```

`comptime` means the value is known while the program is being compiled.

### B.24 Builtins

Zig builtins start with `@`.

```zig
@import("std")
@sizeOf(i32)
@alignOf(i32)
@typeInfo(i32)
@panic("failed")
```

Common examples:

| Builtin | Use |
|---|---|
| `@import` | Import a file or package |
| `@sizeOf` | Get type size in bytes |
| `@alignOf` | Get type alignment |
| `@typeInfo` | Inspect a type |
| `@panic` | Stop the program |
| `@compileError` | Emit a compile-time error |

### B.25 Tests

```zig
test "add works" {
    try std.testing.expect(add(2, 3) == 5);
}
```

Run tests:

```bash
zig test main.zig
```

### B.26 Common Format Strings

```zig
std.debug.print("{}\n", .{number});
std.debug.print("{s}\n", .{string});
std.debug.print("{any}\n", .{value});
```

| Format | Meaning |
|---|---|
| `{}` | Default formatting |
| `{s}` | String |
| `{any}` | Debug-style formatting |

### B.27 Imports

```zig
const std = @import("std");
const math = @import("math.zig");
```

If `math.zig` contains:

```zig
pub fn add(a: i32, b: i32) i32 {
    return a + b;
}
```

You can call:

```zig
const x = math.add(1, 2);
```

### B.28 Public Declarations

```zig
pub fn run() void {}
```

`pub` makes a declaration visible outside the file or namespace.

Without `pub`, the declaration is private to that file or namespace.

### B.29 Undefined

```zig
var x: i32 = undefined;
```

`undefined` means the value is not initialized.

Do not read an undefined value. Use it only when you will definitely assign a real value before reading.

### B.30 Unreachable

```zig
unreachable;
```

Use `unreachable` to say: execution must never reach this point.

Example:

```zig
switch (value) {
    0 => {},
    1 => {},
    else => unreachable,
}
```

Use it carefully. If the program reaches `unreachable`, that is a bug.

### B.31 Small Mental Model

Zig code usually asks you to make things visible:

| Question | Zig usually wants |
|---|---|
| Can this fail? | Put the error in the type |
| Does this allocate? | Pass an allocator |
| Is this nullable? | Use `?T` |
| Is this compile-time? | Use `comptime` |
| Is cleanup needed? | Use `defer` |
| Is memory shared? | Use pointers or slices explicitly |

The cheat sheet is enough for reading small Zig programs. The details come from the chapters.

