# Unwrapping Optionals

### Unwrapping Optionals

An optional value cannot be used as the payload type until it is unwrapped.

This is wrong:

```zig
const x: ?i32 = 10;
const y: i32 = x; // error
```

`x` is not an `i32`. It is a `?i32`.

To get the integer out, test the optional:

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

pub fn main() void {
    const x: ?i32 = 10;

    if (x) |value| {
        std.debug.print("{d}\n", .{value});
    }
}
```

The syntax

```zig
if (x) |value| {
    ...
}
```

means: if `x` contains a value, bind that value to the name `value`.

Inside the block, `value` has type `i32`, not `?i32`.

If the optional is `null`, the block is skipped.

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

pub fn main() void {
    const x: ?i32 = null;

    if (x) |value| {
        std.debug.print("{d}\n", .{value});
    }
}
```

This program prints nothing.

Use `else` to handle the missing case:

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

pub fn main() void {
    const x: ?i32 = null;

    if (x) |value| {
        std.debug.print("value: {d}\n", .{value});
    } else {
        std.debug.print("no value\n", .{});
    }
}
```

The output is:

```text
no value
```

An optional can also be unwrapped with `orelse`.

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

pub fn main() void {
    const x: ?i32 = null;
    const y: i32 = x orelse 0;

    std.debug.print("{d}\n", .{y});
}
```

The expression

```zig
x orelse 0
```

means: use the value inside `x` if it exists; otherwise use `0`.

Here `y` is an `i32`.

`orelse` is useful for defaults:

```zig
fn portOrDefault(port: ?u16) u16 {
    return port orelse 8080;
}
```

If `port` has a value, that value is returned. If `port` is `null`, the function returns `8080`.

There is also a force unwrap operator:

```zig
const x: ?i32 = 10;
const y: i32 = x.?;
```

The expression `x.?` extracts the payload.

It is safe only if `x` is not `null`.

This will fail at runtime in safe builds:

```zig
const x: ?i32 = null;
const y: i32 = x.?;
```

Use `.?` only when the program has already proved that the optional is not null.

For example:

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

pub fn main() void {
    const x: ?i32 = 10;

    if (x != null) {
        const y = x.?;
        std.debug.print("{d}\n", .{y});
    }
}
```

This works, but the payload capture form is clearer:

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

Prefer the capture form when possible. It keeps the proof and the value together.

Exercise 9-8. Write a function `valueOrZero` that takes `?i32` and returns `i32`.

Exercise 9-9. Write a function `printOptionalName` that takes `?[]const u8` and prints either the name or `"(none)"`.

Exercise 9-10. Rewrite a force unwrap with an `if` capture.

