# What `comptime` Means

### What `comptime` Means

A Zig program runs in two stages.

First, the compiler runs.

Then the program runs.

Most languages keep these stages mostly separate. Zig does not. Zig allows parts of a program to execute while the compiler is still compiling the program. This is called compile-time execution.

The keyword is:

```zig
comptime
```

Compile-time execution is one of the central ideas in Zig. It replaces much of what other languages solve with preprocessors, templates, macros, code generators, or special metaprogramming systems.

The simplest example uses a value known during compilation.

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

pub fn main() void {
    const x = comptime fibonacci(10);
    std.debug.print("{d}\n", .{x});
}

fn fibonacci(n: u32) u32 {
    if (n < 2)
        return n;

    return fibonacci(n - 1) + fibonacci(n - 2);
}
```

The output is:

```text
55
```

The important point is not the result. The important point is when the work happens.

`fibonacci(10)` runs while the compiler is compiling the program. The executable already contains the value `55`.

The generated machine code does not need to compute Fibonacci numbers at runtime.

A compile-time value must be known completely during compilation.

This is valid:

```zig
const n = comptime 4 * 8;
```

This is not:

```zig
var x: u32 = 10;
const y = comptime x * 2;
```

The compiler cannot evaluate `x * 2` at compile time because `x` is a runtime variable.

Compile-time execution uses the same language as runtime execution. There is no second metaprogramming language.

Functions are ordinary functions:

```zig
fn square(x: u32) u32 {
    return x * x;
}
```

They can run at runtime:

```zig
const a = square(5);
```

Or at compile time:

```zig
const b = comptime square(5);
```

The language does not split these into separate systems.

This becomes more useful when types are involved.

In Zig, types are values known at compile time.

A function can receive a type as an argument:

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

fn printType(comptime T: type) void {
    std.debug.print("{s}\n", .{@typeName(T)});
}

pub fn main() void {
    printType(i32);
    printType(f64);
}
```

The output is:

```text
i32
f64
```

The parameter:

```zig
comptime T: type
```

means:

* `T` is known during compilation
* `T` itself is a type value

This is the basis of generic programming in Zig.

Compile-time execution can also control declarations.

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

pub fn main() void {
    comptime {
        std.debug.print("during compilation\n", .{});
    }

    std.debug.print("during execution\n", .{});
}
```

The first message appears while the compiler is compiling the program. The second appears when the executable runs.

Compile-time blocks are often used for validation.

```zig
comptime {
    if (@sizeOf(usize) < 8) {
        @compileError("64-bit system required");
    }
}
```

If the condition fails, compilation stops immediately.

Compile-time execution is not a textual substitution system. It is not like the C preprocessor.

The compiler executes Zig code with full type checking and semantic analysis.

This matters because generated code remains ordinary Zig code. Errors are usually easier to understand than macro expansion errors in other systems.

A common use of `comptime` is generating specialized code.

```zig
fn add(comptime T: type, a: T, b: T) T {
    return a + b;
}
```

The calls:

```zig
add(i32, 3, 4)
add(f64, 1.5, 2.5)
```

produce versions specialized for different types.

The compiler knows the exact type in each case.

Compile-time execution is powerful, but it should stay simple.

Use it when:

* types must be selected
* declarations must be generated
* validation should happen during compilation
* runtime overhead should disappear

Do not use it merely because it exists.

Most ordinary logic should still run at runtime.

Exercise 10-1. Write a function `cube` and evaluate it with `comptime`.

Exercise 10-2. Write a function that receives `comptime T: type` and prints the type name.

Exercise 10-3. Use a `comptime` block to reject systems where `@sizeOf(usize)` is smaller than 8.

Exercise 10-4. Write a generic `max` function using a compile-time type parameter.

