Browse Source

add ex082 anon structs 3

Dave Gauer 4 years ago
parent
commit
c43e5480c6
3 changed files with 150 additions and 0 deletions
  1. 5 0
      build.zig
  2. 125 0
      exercises/082_anonymous_structs3.zig
  3. 20 0
      patches/patches/082_anonymous_structs3.patch

+ 5 - 0
build.zig

@@ -404,6 +404,11 @@ const exercises = [_]Exercise{
         .main_file = "081_anonymous_structs2.zig",
         .main_file = "081_anonymous_structs2.zig",
         .output = "x:205 y:187 radius:12",
         .output = "x:205 y:187 radius:12",
     },
     },
+    .{
+        .main_file = "082_anonymous_structs3.zig",
+        .output = "\"0\"(bool):true \"1\"(bool):false \"2\"(i32):42 \"3\"(f32):3.14159202e+00",
+        .hint = "This one is a challenge! But you have everything you need."
+    },
 };
 };
 
 
 /// Check the zig version to make sure it can compile the examples properly.
 /// Check the zig version to make sure it can compile the examples properly.

+ 125 - 0
exercises/082_anonymous_structs3.zig

@@ -0,0 +1,125 @@
+//
+// You can even create anonymous struct literals without field
+// names:
+//
+//     .{
+//         false,
+//         @as(u32, 15);
+//         @as(i64, 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,
+        //             field_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}\"({s}):{any} ", .{
+            field.???,
+            field.???,
+            ???,
+        });
+    }
+}

+ 20 - 0
patches/patches/082_anonymous_structs3.patch

@@ -0,0 +1,20 @@
+85c85
+<     const fields = ???;
+---
+>     const fields = @typeInfo(@TypeOf(tuple)).Struct.fields;
+92c92
+<     for (fields) |field| {
+---
+>     inline for (fields) |field| {
+116c116
+<         //         @field(foo, "x"); // returns the value at foo.x
+---
+>         //         @field(foo, "x");
+120,122c120,122
+<             field.???,
+<             field.???,
+<             ???,
+---
+>             field.name,
+>             field.field_type,
+>             @field(tuple, field.name),