Socialify

Folder ..

Viewing 082_anonymous_structs3.zig
125 lines (120 loc) • 3.5 KB

  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
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
//
// You can even create anonymous struct literals without field
// names:
//
//     .{
//         false,
//         @as(u32, 15),
//         @as(f64, 67.12)
//     }
//
// We call these "tuples", which is a term used by many
// programming languages for a data type with fields referenced
// by index order rather than name. To make this possible, the Zig
// compiler automatically assigns numeric field names 0, 1, 2,
// etc. to the struct.
//
// Since bare numbers are not legal identifiers (foo.0 is a
// syntax error), we have to quote them with the @"" syntax.
// Example:
//
//     const foo = .{ true, false };
//
//     print("{} {}\n", .{foo.@"0", foo.@"1"});
//
// The example above prints "true false".
//
// Hey, WAIT A SECOND...
//
// If a .{} thing is what the print function wants, do we need to
// break our "tuple" apart and put it in another one? No! It's
// redundant! This will print the same thing:
//
//     print("{} {}\n", foo);
//
// Aha! So now we know that print() takes a "tuple". Things are
// really starting to come together now.
//
const print = @import("std").debug.print;

pub fn main() void {
    // A "tuple":
    const foo = .{
        true,
        false,
        @as(i32, 42),
        @as(f32, 3.141592),
    };

    // We'll be implementing this:
    printTuple(foo);

    // This is just for fun, because we can:
    const nothing = .{};
    print("\n", nothing);
}

// Let's make our own generic "tuple" printer. This should take a
// "tuple" and print out each field in the following format:
//
//     "name"(type):value
//
// Example:
//
//     "0"(bool):true
//
// You'll be putting this together. But don't worry, everything
// you need is documented in the comments.
fn printTuple(tuple: anytype) void {
    // 1. Get a list of fields in the input 'tuple'
    // parameter. You'll need:
    //
    //     @TypeOf() - takes a value, returns its type.
    //
    //     @typeInfo() - takes a type, returns a TypeInfo union
    //                   with fields specific to that type.
    //
    //     The list of a struct type's fields can be found in
    //     TypeInfo's Struct.fields.
    //
    //     Example:
    //
    //         @typeInfo(Circle).Struct.fields
    //
    // This will be an array of StructFields.
    const fields = ???;

    // 2. Loop through each field. This must be done at compile
    // time.
    //
    //     Hint: remember 'inline' loops?
    //
    for (fields) |field| {
        // 3. Print the field's name, type, and value.
        //
        //     Each 'field' in this loop is one of these:
        //
        //         pub const StructField = struct {
        //             name: []const u8,
        //             type: type,
        //             default_value: anytype,
        //             is_comptime: bool,
        //             alignment: comptime_int,
        //         };
        //
        //     You'll need this builtin:
        //
        //         @field(lhs: anytype, comptime field_name: []const u8)
        //
        //     The first parameter is the value to be accessed,
        //     the second parameter is a string with the name of
        //     the field you wish to access. The value of the
        //     field is returned.
        //
        //     Example:
        //
        //         @field(foo, "x"); // returns the value at foo.x
        //
        // The first field should print as: "0"(bool):true
        print("\"{s}\"({any}):{any} ", .{
            field.???,
            field.???,
            ???,
        });
    }
}