# Names and Declarations

### Names and Declarations

A Zig program is made from declarations.

A declaration gives a name to something. The name may refer to a value, a function, a type, or an imported module.

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

const count = 10;

pub fn main() void {
    std.debug.print("{d}\n", .{count});
}
```

There are three declarations here.

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

This declares the name `std`.

```zig
const count = 10;
```

This declares the name `count`.

```zig
pub fn main() void {
    ...
}
```

This declares the function `main`.

A `const` declaration has this form:

```zig
const name = value;
```

The name is fixed. It cannot later be assigned another value.

```zig
const n = 3;
n = 4; // error
```

A `var` declaration has this form:

```zig
var name = value;
```

The name may be assigned another value.

```zig
var n = 3;
n = 4;
```

A declaration may also give the type explicitly.

```zig
const x: i32 = 10;
var y: i32 = 20;
```

The part after the colon is the type. Here both `x` and `y` have type `i32`, a signed 32-bit integer.

When the type is omitted, Zig infers it from the value.

```zig
const x = 10;
```

This is often enough. But explicit types are useful when the exact size matters.

```zig
const small: u8 = 255;
```

`u8` is an unsigned 8-bit integer. It can hold values from `0` to `255`.

A name is visible inside its scope. A scope is a region of code surrounded by braces.

```zig
pub fn main() void {
    const a = 1;

    {
        const b = 2;
        std.debug.print("{d} {d}\n", .{ a, b });
    }

    std.debug.print("{d}\n", .{a});
    // b is not visible here
}
```

The name `a` is visible in the whole function after its declaration. The name `b` is visible only inside the inner block.

Declarations at the top level of a file are file declarations.

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

pub fn main() void {
    std.debug.print("{s}\n", .{message});
}
```

The function `main` can use `std` and `message` because they are declared at file scope.

A declaration can be public.

```zig
pub const version = 1;
```

`pub` means the declaration can be used from another file that imports this file. Without `pub`, the declaration is private to the file.

Function declarations use `fn`.

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

This declares a function named `add`. It takes two `i32` values and returns an `i32`.

A public function uses `pub fn`.

```zig
pub fn main() void {
    const sum = add(2, 3);
    std.debug.print("{d}\n", .{sum});
}
```

Zig does not require declarations to appear before use at file scope. This is valid:

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

pub fn main() void {
    const sum = add(2, 3);
    std.debug.print("{d}\n", .{sum});
}

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

The compiler sees the whole file.

Inside a block, declarations are read in order. A local name must be declared before it is used.

```zig
pub fn main() void {
    const x = 1;
    const y = x + 1;
    std.debug.print("{d}\n", .{y});
}
```

A name should say what the value means.

```zig
const bytes_read = 128;
const max_line_len = 4096;
```

Short names are useful for small local values.

```zig
var i: usize = 0;
```

Longer names are better when the value lives longer or carries more meaning.

```zig
const input_file_name = "data.txt";
```

A declaration is simple, but it is the main unit of Zig code. You declare names, give them values or definitions, and use those names to build the program.

Exercises:

1. Declare a constant named `answer` with value `42` and print it.

2. Declare a variable named `n`, set it to `1`, then assign `2`, then print it.

3. Write a function `square` that takes an `i32` and returns its square.

4. Move `square` below `main` and verify that the program still compiles.

5. Create an inner block with a local constant, then try to use that constant outside the block.

