# Default Field Values

### Default Field Values

A struct field can have a default value.

A default field value is used when you create a struct value and do not provide that field yourself.

```zig
const Config = struct {
    port: u16 = 8080,
    debug: bool = false,
};
```

This defines a struct type named `Config`.

It has two fields:

```zig
port: u16 = 8080
debug: bool = false
```

The field `port` has the default value `8080`.

The field `debug` has the default value `false`.

You can create a `Config` value like this:

```zig
const config = Config{};
```

This uses both default values.

So the value is the same as:

```zig
const config = Config{
    .port = 8080,
    .debug = false,
};
```

Default field values let you define the normal case once, then override only the fields that need to change.

#### Creating a Value with Defaults

Here is a complete program:

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

const Config = struct {
    port: u16 = 8080,
    debug: bool = false,
};

pub fn main() void {
    const config = Config{};

    std.debug.print("port = {}, debug = {}\n", .{
        config.port,
        config.debug,
    });
}
```

Output:

```text
port = 8080, debug = false
```

The expression `Config{}` creates a value where all fields use their defaults.

This only works because every field in `Config` has a default value.

#### Overriding One Field

You can override one field and keep the others unchanged.

```zig
const config = Config{
    .debug = true,
};
```

Now `debug` is `true`, but `port` still uses its default value.

The full value is:

```zig
const config = Config{
    .port = 8080,
    .debug = true,
};
```

This is useful for configuration data.

```zig
const ServerConfig = struct {
    host: []const u8 = "127.0.0.1",
    port: u16 = 8080,
    max_connections: usize = 1024,
    debug: bool = false,
};

const dev = ServerConfig{
    .debug = true,
};

const prod = ServerConfig{
    .host = "0.0.0.0",
    .port = 80,
};
```

The `dev` config changes only `debug`.

The `prod` config changes only `host` and `port`.

Everything else uses the default.

#### Fields Without Defaults

A field does not need to have a default.

```zig
const User = struct {
    id: u64,
    name: []const u8,
    active: bool = true,
};
```

Here, `id` and `name` have no default values.

The field `active` has a default value.

So this is valid:

```zig
const user = User{
    .id = 1,
    .name = "Ada",
};
```

The missing `active` field becomes `true`.

This is the same as:

```zig
const user = User{
    .id = 1,
    .name = "Ada",
    .active = true,
};
```

But this is not valid:

```zig
const user = User{};
```

Zig cannot invent values for `id` and `name`.

You must provide every field that has no default.

#### Defaults Are Part of the Type Definition

Default values are written inside the struct definition:

```zig
const Options = struct {
    verbose: bool = false,
    retries: u8 = 3,
};
```

That means every place that uses `Options` sees the same defaults.

This gives the type a single definition of its normal state.

Without defaults, code can become repetitive:

```zig
const a = Options{
    .verbose = false,
    .retries = 3,
};

const b = Options{
    .verbose = false,
    .retries = 3,
};
```

With defaults, the same code becomes cleaner:

```zig
const a = Options{};
const b = Options{};
```

The defaults live in one place.

#### Default Values Can Use Constants

A default value can refer to constants that are visible at that point.

```zig
const default_port: u16 = 8080;

const Config = struct {
    port: u16 = default_port,
    debug: bool = false,
};
```

You can also put constants inside the struct:

```zig
const Config = struct {
    const default_port: u16 = 8080;

    port: u16 = default_port,
    debug: bool = false,
};
```

Now `default_port` belongs to the `Config` namespace.

You can refer to it as:

```zig
Config.default_port
```

This is useful when the default itself is meaningful and should have a name.

#### Default Values and `init`

Default field values do not replace `init` functions.

They solve different problems.

Use default field values when a field has a simple normal value:

```zig
const LoggerConfig = struct {
    level: []const u8 = "info",
    color: bool = true,
};
```

Use an `init` function when creation needs logic:

```zig
const Buffer = struct {
    data: []u8,
    len: usize = 0,

    pub fn init(data: []u8) Buffer {
        return Buffer{
            .data = data,
        };
    }
};
```

Here, `data` must be provided by the caller. But `len` has a natural default of `0`.

So the `init` function only asks for the required field:

```zig
var storage: [1024]u8 = undefined;
const buffer = Buffer.init(storage[0..]);
```

The returned value uses:

```zig
.len = 0
```

from the default field value.

#### Default Values and Mutable Structs

Default values only affect creation.

After the value exists, fields behave like normal fields.

```zig
const Counter = struct {
    value: i32 = 0,
};

pub fn main() void {
    var c = Counter{};

    c.value += 1;
    c.value += 1;
}
```

The default gives `value` the initial value `0`.

Then the program changes it to `2`.

A default value is not a permanent rule. It is only an initial value.

#### Defaults Do Not Mean Optional

A default value is not the same as an optional field.

This field always exists:

```zig
debug: bool = false
```

Every `Config` value has a `debug` field. If you do not provide it, Zig fills in `false`.

An optional field uses `?`:

```zig
log_path: ?[]const u8 = null
```

This means the field may contain a path, or it may contain `null`.

Example:

```zig
const Config = struct {
    debug: bool = false,
    log_path: ?[]const u8 = null,
};
```

Now `debug` always has a boolean value.

`log_path` may or may not have a string.

```zig
const a = Config{};
const b = Config{
    .log_path = "/tmp/app.log",
};
```

In `a`, `log_path` is `null`.

In `b`, `log_path` contains `"/tmp/app.log"`.

#### A Practical Example

Suppose we are writing options for a command-line tool.

```zig
const Options = struct {
    input_path: []const u8,
    output_path: []const u8 = "out.txt",
    verbose: bool = false,
    threads: usize = 1,
};
```

The input path is required.

The output path, verbose flag, and thread count have defaults.

We can create a simple value:

```zig
const options = Options{
    .input_path = "data.txt",
};
```

This means:

```text
input_path = "data.txt"
output_path = "out.txt"
verbose = false
threads = 1
```

We can also override some fields:

```zig
const options = Options{
    .input_path = "data.txt",
    .output_path = "result.txt",
    .threads = 4,
};
```

Now only `verbose` uses its default.

This gives a clean shape to configuration data. Required fields stay visible. Optional settings stay out of the way until needed.

#### Common Mistake: Forgetting Required Fields

This struct has one required field:

```zig
const User = struct {
    name: []const u8,
    active: bool = true,
};
```

This works:

```zig
const user = User{
    .name = "Ada",
};
```

This does not:

```zig
const user = User{};
```

The field `name` has no default value, so Zig requires it.

The rule is simple: every field must get a value, either from the literal or from a default.

#### Common Mistake: Thinking Defaults Are Shared State

A default value does not create shared mutable state between struct values.

Each struct value gets its own field value.

```zig
const Counter = struct {
    value: i32 = 0,
};

var a = Counter{};
var b = Counter{};

a.value = 10;
```

After this:

```text
a.value is 10
b.value is 0
```

The default was used to initialize both values. After that, they are separate values.

#### The Main Idea

Default field values make struct creation easier.

They let the type define its normal state:

```zig
const Config = struct {
    port: u16 = 8080,
    debug: bool = false,
};
```

Then code can create ordinary values with less repetition:

```zig
const config = Config{};
```

Use defaults for simple, predictable initial values. Keep required fields without defaults so the caller must provide them explicitly.

