082_anonymous_structs3.zig 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. //
  2. // You can even create anonymous struct literals without field
  3. // names:
  4. //
  5. // .{
  6. // false,
  7. // @as(u32, 15),
  8. // @as(f64, 67.12)
  9. // }
  10. //
  11. // We call these "tuples", which is a term used by many
  12. // programming languages for a data type with fields referenced
  13. // by index order rather than name. To make this possible, the Zig
  14. // compiler automatically assigns numeric field names 0, 1, 2,
  15. // etc. to the struct.
  16. //
  17. // Since bare numbers are not legal identifiers (foo.0 is a
  18. // syntax error), we have to quote them with the @"" syntax.
  19. // Example:
  20. //
  21. // const foo = .{ true, false };
  22. //
  23. // print("{} {}\n", .{foo.@"0", foo.@"1"});
  24. //
  25. // The example above prints "true false".
  26. //
  27. // Hey, WAIT A SECOND...
  28. //
  29. // If a .{} thing is what the print function wants, do we need to
  30. // break our "tuple" apart and put it in another one? No! It's
  31. // redundant! This will print the same thing:
  32. //
  33. // print("{} {}\n", foo);
  34. //
  35. // Aha! So now we know that print() takes a "tuple". Things are
  36. // really starting to come together now.
  37. //
  38. const print = @import("std").debug.print;
  39. pub fn main() void {
  40. // A "tuple":
  41. const foo = .{
  42. true,
  43. false,
  44. @as(i32, 42),
  45. @as(f32, 3.141592),
  46. };
  47. // We'll be implementing this:
  48. printTuple(foo);
  49. // This is just for fun, because we can:
  50. const nothing = .{};
  51. print("\n", nothing);
  52. }
  53. // Let's make our own generic "tuple" printer. This should take a
  54. // "tuple" and print out each field in the following format:
  55. //
  56. // "name"(type):value
  57. //
  58. // Example:
  59. //
  60. // "0"(bool):true
  61. //
  62. // You'll be putting this together. But don't worry, everything
  63. // you need is documented in the comments.
  64. fn printTuple(tuple: anytype) void {
  65. // 1. Get a list of fields in the input 'tuple'
  66. // parameter. You'll need:
  67. //
  68. // @TypeOf() - takes a value, returns its type.
  69. //
  70. // @typeInfo() - takes a type, returns a TypeInfo union
  71. // with fields specific to that type.
  72. //
  73. // The list of a struct type's fields can be found in
  74. // TypeInfo's @"struct".fields.
  75. //
  76. // Example:
  77. //
  78. // @typeInfo(Circle).@"struct".fields
  79. //
  80. // This will be an array of StructFields.
  81. const fields = ???;
  82. // 2. Loop through each field. This must be done at compile
  83. // time.
  84. //
  85. // Hint: remember 'inline' loops?
  86. //
  87. for (fields) |field| {
  88. // 3. Print the field's name, type, and value.
  89. //
  90. // Each 'field' in this loop is one of these:
  91. //
  92. // pub const StructField = struct {
  93. // name: [:0]const u8,
  94. // type: type,
  95. // default_value_ptr: ?*const anyopaque,
  96. // is_comptime: bool,
  97. // alignment: comptime_int,
  98. // };
  99. //
  100. // Note we will learn about 'anyopaque' type later
  101. //
  102. // You'll need this builtin:
  103. //
  104. // @field(lhs: anytype, comptime field_name: []const u8)
  105. //
  106. // The first parameter is the value to be accessed,
  107. // the second parameter is a string with the name of
  108. // the field you wish to access. The value of the
  109. // field is returned.
  110. //
  111. // Example:
  112. //
  113. // @field(foo, "x"); // returns the value at foo.x
  114. //
  115. // The first field should print as: "0"(bool):true
  116. print("\"{s}\"({any}):{any} ", .{
  117. field.???,
  118. field.???,
  119. ???,
  120. });
  121. }
  122. }