# Importing Files

### Importing Files

Large programs are divided into smaller files. Zig uses `@import` to include declarations from another file.

Suppose a directory contains these files:

```text
main.zig
math.zig
```

The file `math.zig` contains:

```zig
pub fn add(a: i32, b: i32) i32 {
    return a + b;
}

pub fn sub(a: i32, b: i32) i32 {
    return a - b;
}
```

Another file may import it:

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

pub fn main() void {
    const x = math.add(10, 20);
    const y = math.sub(50, 8);

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

The output is:

```text
30 42
```

The expression:

```zig
@import("math.zig")
```

loads another Zig source file.

The result is a namespace-like object containing the file's public declarations.

The name:

```zig
math
```

is chosen by the programmer. Any valid identifier may be used:

```zig
const m = @import("math.zig");
```

Then:

```zig
m.add(1, 2)
```

calls the imported function.

Imports are resolved at compile time.

If the imported file contains an error, compilation fails even if the faulty declaration is never used.

Only public declarations are visible:

```zig
fn helper() void {}

pub fn work() void {
    helper();
}
```

The caller may use:

```zig
module.work();
```

but not:

```zig
module.helper()
```

because `helper` is private.

Imports may also be nested.

Suppose:

```text
main.zig
util/
    math.zig
```

Then:

```zig
const math = @import("util/math.zig");
```

imports the file.

Relative paths are commonly used for local modules.

A file may import many modules:

```zig
const std = @import("std");
const math = @import("math.zig");
const parser = @import("parser.zig");
```

Each imported file has its own declarations and private state.

Imports are declarations like any other:

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

Here `std` is simply a constant whose value comes from the import expression.

This means imports can appear inside functions:

```zig
pub fn main() void {
    const std = @import("std");

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

although imports are usually placed near the top of the file.

Importing a file does not copy source text into another file, as with the C preprocessor `#include`.

Zig imports declarations semantically. This avoids many problems common in textual inclusion systems.

A Zig file is itself a module.

For example:

```zig
pub const version = "0.16";
```

makes `version` accessible through imports.

Modules may expose constants, variables, functions, types, and tests.

Imported declarations are accessed with dot notation:

```zig
math.add(1, 2)
std.debug.print(...)
```

This keeps namespaces explicit and avoids many name collisions.

A common style is:

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

in almost every source file.

The standard library is large, but importing `std` does not automatically include all of it in the final executable. Zig compiles only what is used.

Exercise 4-17. Split a calculator program across two files.

Exercise 4-18. Create a module `geometry.zig` with public functions `area` and `perimeter`.

Exercise 4-19. Import the standard library inside a function instead of at file scope.

Exercise 4-20. Why is Zig's import system different from C's `#include` model?

