mirror of
https://codeberg.org/andyscott/ziglings.git
synced 2024-11-09 19:40:48 -05:00
add ex082 anon structs 3
This commit is contained in:
parent
c0bbbee176
commit
c43e5480c6
3 changed files with 150 additions and 0 deletions
|
@ -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
exercises/082_anonymous_structs3.zig
Normal file
125
exercises/082_anonymous_structs3.zig
Normal file
|
@ -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
patches/patches/082_anonymous_structs3.patch
Normal file
20
patches/patches/082_anonymous_structs3.patch
Normal file
|
@ -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),
|
Loading…
Reference in a new issue