# If Expressions

> No truthiness: if takes a bool.

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

test "if as a statement" {
    const a = true;
    var x: u16 = 0;
    if (a) {
        x += 1;
    } else {
        x += 2;
    }
    try expect(x == 1);
}

test "if as an expression" {
    const a = true;
    // The ternary equivalent; both branches must yield the same type.
    const x: u16 = if (a) 1 else 2;
    try expect(x == 1);
}

test "if unwraps an optional" {
    const maybe: ?u8 = 42;
    const doubled: u16 = if (maybe) |value| value * 2 else 0;
    try expect(doubled == 84);
}
```

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

There is no truthiness in Zig. `if (1)` does not compile; neither does
`if (pointer)`. The condition must be a `bool`, which removes an entire family
of bugs where a value is accidentally treated as a flag.

## `if` produces a value

Zig has no ternary operator because it does not need one:

```zig
const x: u16 = if (a) 1 else 2;
```

Both branches must agree on a type. Used as an expression, the `else` is
mandatory: there would otherwise be no value when the condition is false.

## Unwrapping

`if` is also how you get inside an optional, using payload capture:

```zig
if (maybe) |value| { ... } else { ... }
```

The same shape works for error unions with `else |err|`. This is a recurring
theme: the check and the unwrap are one construct, so they cannot fall out of
sync.
