# The Optional Type

### The Optional Type

Sometimes a value may or may not exist.

A search may fail. A pointer may be empty. A function may have nothing useful to return.

Zig represents this with an optional type.

An optional type is written with `?` before another type:

```zig
?i32
```

This means:

> either an `i32` value, or `null`

Here is a small example:

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

pub fn main() void {
    const a: ?i32 = 42;
    const b: ?i32 = null;

    std.debug.print("{any}\n", .{a});
    std.debug.print("{any}\n", .{b});
}
```

The output is:

```text
42
null
```

An optional type stores one of two states:

1. a real value
2. `null`

The value must match the base type.

These are valid:

```zig
const x: ?i32 = 10;
const y: ?bool = true;
const z: ?f64 = null;
```

This is not:

```zig
const n: ?i32 = "hello";
```

because `"hello"` is not an integer.

Optional types are common in Zig because the language avoids hidden values and implicit failure states. A missing value is represented directly in the type.

For example, suppose we want a function that finds the first even number in an array.

If an even number exists, return it.

If none exists, return `null`.

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

fn firstEven(numbers: []const i32) ?i32 {
    for (numbers) |n| {
        if (n % 2 == 0) {
            return n;
        }
    }

    return null;
}

pub fn main() void {
    const values = [_]i32{ 1, 3, 7, 8, 9 };

    const result = firstEven(&values);

    std.debug.print("{any}\n", .{result});
}
```

The output is:

```text
8
```

If the array contains no even numbers:

```zig
const values = [_]i32{ 1, 3, 5, 7 };
```

the output becomes:

```text
null
```

Optional types are different from error unions.

This:

```zig
?i32
```

means:

> a value may be missing

This:

```zig
error{Failed}!i32
```

means:

> an operation may fail

The difference matters.

A missing value is often normal behavior. An error usually means something went wrong.

Optional types are also used heavily with pointers:

```zig
?*i32
```

This means:

> either a pointer to `i32`, or `null`

This is similar to nullable pointers in C, but Zig makes the possibility explicit in the type system.

A plain pointer:

```zig
*i32
```

cannot be null.

The compiler checks this rule.

Optional values must usually be unwrapped before use. That is the subject of the next section.

Exercise 9-1. Declare optional values of type `?bool`, `?u32`, and `?f64`.

Exercise 9-2. Write a function that returns the first negative number in an array, or `null` if none exists.

Exercise 9-3. Change `firstEven` so it returns a pointer to the matching value instead of the value itself.

Exercise 9-4. Why is `?i32` safer than using `-1` as a special “not found” value?

