# `if` Expressions

### `if` Expressions

In Zig, `if` is an expression. It can produce a value.

```zig
const max = if (a > b) a else b;
```

This is common Zig style. The `if` expression chooses one of two values.

The condition must be a boolean value. Zig does not convert integers to booleans automatically.

This is correct:

```zig
if (x != 0) {
    // ...
}
```

This is wrong:

```zig
if (x) {
    // ...
}
```

If `x` is an integer, the compiler rejects it.

The basic form is:

```zig
if (condition) expression1 else expression2
```

Both branches must produce compatible types.

```zig
const value = if (true) 1 else 2;
```

This is valid because both branches are integers.

This is not:

```zig
const value = if (true) 1 else "hello";
```

The branches have different types.

Braces are optional when a branch contains a single expression.

```zig
const sign = if (n < 0) -1 else 1;
```

Longer branches usually use blocks.

```zig
const kind = if (n == 0) {
    "zero"
} else if (n < 0) {
    "negative"
} else {
    "positive"
};
```

The final semicolon belongs to the declaration, not the `if`.

Because `if` is an expression, it fits naturally into assignments and return statements.

```zig
fn abs(x: i32) i32 {
    return if (x < 0) -x else x;
}
```

The whole `if` expression becomes the return value.

An `if` branch may contain blocks.

```zig
const result = if (n > 100) blk: {
    const half = n / 2;
    break :blk half;
} else blk: {
    const doubled = n * 2;
    break :blk doubled;
};
```

This combines block expressions with `if`.

Conditions are evaluated from left to right.

```zig
if (a and b) {
    // ...
}
```

`and` stops early if the left side is false.

```zig
if (a or b) {
    // ...
}
```

`or` stops early if the left side is true.

These are short-circuit operators.

Optional values work naturally with `if`.

```zig
const maybe_name: ?[]const u8 = "zig";

if (maybe_name) |name| {
    std.debug.print("{s}\n", .{name});
}
```

If the optional contains a value, the value is captured in `name`.

Error unions also work with `if`.

```zig
const result: anyerror!i32 = 42;

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

The success value is captured in the first branch. The error value is captured in the `else` branch.

This style appears often in Zig code because error handling is explicit.

An `if` expression may also produce `void`.

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

Here there is no `else` branch because the result is not used.

The type of the whole expression is `void`.

Nested `if` expressions are common, but deep nesting is usually avoided.

```zig
if (x < 0) {
    // ...
} else if (x == 0) {
    // ...
} else {
    // ...
}
```

This is clearer than many separate `if` statements.

Exercise 3-5. Write an `if` expression that returns the smaller of two integers.

Exercise 3-6. Rewrite an ordinary `if` statement as an expression.

Exercise 3-7. Use `if` with an optional value.

Exercise 3-8. Write a function that returns `"even"` or `"odd"` using an `if` expression.

