aboutsummaryrefslogtreecommitdiff
path: root/exercises/066_comptime.zig
blob: 262bf6f64d60a0e62213bb7beeb06bd05dd8662a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
//
// "Compile time" is a program's environment while it is being
// compiled. In contrast, "run time" is the environment while the
// compiled program is executing (traditionally as machine code
// on a hardware CPU).
//
// Errors make an easy example:
//
// 1. Compile-time error: caught by the compiler, usually
//    resulting in a message to the programmer.
//
// 2. Runtime error: either caught by the running program itself
//    or by the host hardware or operating system. Could be
//    gracefully caught and handled or could cause the computer
//    to crash (or halt and catch fire)!
//
// All compiled languages must perform a certain amount of logic
// at compile time in order to analyze the code, maintain a table
// of symbols (such as variable and function names), etc.
//
// Optimizing compilers can also figure out how much of a program
// can be pre-computed or "inlined" at compile time to make the
// resulting program more efficient. Smart compilers can even
// "unroll" loops, turning their logic into a fast linear
// sequence of statements (at the usually very slight expense of
// the increased size of the repeated code).
//
// Zig takes these concepts further by making these optimizations
// an integral part of the language itself!
// 
const print = @import("std").debug.print;

pub fn main() void  {
    // ALL numeric literals in Zig are of type comptime_int or
    // comptime_float. They are of arbitary size (as big or
    // little as you need).
    //
    // Notice how we don't have to specify a size like "u8",
    // "i32", or "f64" when we assign identifiers immutably with
    // "const".
    //
    // When we use these identifiers in our program, the VALUES
    // are inserted at compile time into the executable code. The
    // IDENTIFIERS "const_int" and "const_float" don't exist in
    // our compiled application!
    const const_int = 12345;
    const const_float = 987.654;

    print("Immutable: {}, {d:.3}; ", .{const_int, const_float});

    // But something changes when we assign the exact same values
    // to identifiers mutably with "var".
    //
    // The literals are STILL comptime_int and comptime_float,
    // but we wish to assign them to identifiers which are
    // mutable at runtime.
    //
    // To be mutable at runtime, these identifiers must refer to
    // areas of memory. In order to refer to areas of memory, Zig
    // must know exactly how much memory to reserve for these
    // values. Therefore, it follows that we just specify numeric
    // types with specific sizes. The comptime numbers will be
    // coerced (if they'll fit!) into your chosen runtime types.
    var var_int = 12345;
    var var_float = 987.654;

    // We can change what is stored at the areas set aside for
    // "var_int" and "var_float" in the running compiled program.
    var_int = 54321;
    var_float = 456.789;

    print("Mutable: {}, {d:.3}; ", .{var_int, var_float});

    // Bonus: Now that we're familiar with Zig's builtins, we can
    // also inspect the types to see what they are, no guessing
    // needed!
    print("Types: {}, {}, {}, {}\n", .{
        @TypeOf(const_int),
        @TypeOf(const_float),
        @TypeOf(var_int),
        @TypeOf(var_float),
    });
}