mirror of
https://codeberg.org/andyscott/ziglings.git
synced 2024-12-22 14:03:10 -05:00
Merge branch 'main' into hello_c
This commit is contained in:
commit
dce731a0ec
4 changed files with 136 additions and 1 deletions
|
@ -164,7 +164,7 @@ Core Language
|
|||
* [x] Quoted identifiers @""
|
||||
* [x] Anonymous structs/tuples/lists
|
||||
* [ ] Async <--- IN PROGRESS!
|
||||
* [ ] Interfaces <--- IN PROGRESS!
|
||||
* [X] Interfaces
|
||||
* [ ] Working with C
|
||||
|
||||
## Contributing
|
||||
|
|
|
@ -469,6 +469,10 @@ const exercises = [_]Exercise{
|
|||
.main_file = "093_hello_c.zig",
|
||||
.output = "Hello C from Zig! - C result ist 17 chars",
|
||||
.C = true,
|
||||
},
|
||||
.{
|
||||
.main_file = "092_interfaces.zig",
|
||||
.output = "Daily Insect Report:\nAnt is alive.\nBee visited 17 flowers.\nGrasshopper hopped 32 meters.",
|
||||
},
|
||||
.{
|
||||
.main_file = "999_the_end.zig",
|
||||
|
|
127
exercises/092_interfaces.zig
Normal file
127
exercises/092_interfaces.zig
Normal file
|
@ -0,0 +1,127 @@
|
|||
//
|
||||
// Remember our ant and bee simulator constructed with unions
|
||||
// back in exercises 55 and 56? There, we demonstrated that
|
||||
// unions allow us to treat different data types in a uniform
|
||||
// manner.
|
||||
//
|
||||
// One neat feature was using tagged unions to create a single
|
||||
// function to print a status for ants *or* bees by switching:
|
||||
//
|
||||
// switch (insect) {
|
||||
// .still_alive => ... // (print ant stuff)
|
||||
// .flowers_visited => ... // (print bee stuff)
|
||||
// }
|
||||
//
|
||||
// Well, that simulation was running just fine until a new insect
|
||||
// arrived in the virtual garden, a grasshopper!
|
||||
//
|
||||
// Doctor Zoraptera started to add grasshopper code to the
|
||||
// program, but then she backed away from her keyboard with an
|
||||
// angry hissing sound. She had realized that having code for
|
||||
// each insect in one place and code to print each insect in
|
||||
// another place was going to become unpleasant to maintain when
|
||||
// the simulation expanded to hundreds of different insects.
|
||||
//
|
||||
// Thankfully, Zig has another comptime feature we can use
|
||||
// to get out of this dilema called the 'inline else'.
|
||||
//
|
||||
// We can replace this redundant code:
|
||||
//
|
||||
// switch (thing) {
|
||||
// .a => |a| special(a),
|
||||
// .b => |b| normal(b),
|
||||
// .c => |c| normal(c),
|
||||
// .d => |d| normal(d),
|
||||
// .e => |e| normal(e),
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// With:
|
||||
//
|
||||
// switch (thing) {
|
||||
// .a => |a| special(a),
|
||||
// inline else |t| => normal(t),
|
||||
// }
|
||||
//
|
||||
// We can have special handling of some cases and then Zig
|
||||
// handles the rest of the matches for us.
|
||||
//
|
||||
// With this feature, you decide to make an Insect union with a
|
||||
// single uniform 'print()' function. All of the insects can
|
||||
// then be responsible for printing themselves. And Doctor
|
||||
// Zoraptera can calm down and stop gnawing on the furniture.
|
||||
//
|
||||
const std = @import("std");
|
||||
|
||||
const Ant = struct {
|
||||
still_alive: bool,
|
||||
|
||||
pub fn print(self: Ant) void {
|
||||
std.debug.print("Ant is {s}.\n", .{if (self.still_alive) "alive" else "dead"});
|
||||
}
|
||||
};
|
||||
|
||||
const Bee = struct {
|
||||
flowers_visited: u16,
|
||||
|
||||
pub fn print(self: Bee) void {
|
||||
std.debug.print("Bee visited {} flowers.\n", .{self.flowers_visited});
|
||||
}
|
||||
};
|
||||
|
||||
// Here's the new grasshopper. Notice how we've also added print
|
||||
// methods to each insect.
|
||||
const Grasshopper = struct {
|
||||
distance_hopped: u16,
|
||||
|
||||
pub fn print(self: Grasshopper) void {
|
||||
std.debug.print("Grasshopper hopped {} meters.\n", .{self.distance_hopped});
|
||||
}
|
||||
};
|
||||
|
||||
const Insect = union(enum) {
|
||||
ant: Ant,
|
||||
bee: Bee,
|
||||
grasshopper: Grasshopper,
|
||||
|
||||
// Thanks to 'inline else', we can think of this print() as
|
||||
// being an interface method. Any member of this union with
|
||||
// with a print() method can be treated uniformly by outside
|
||||
// code without needing to know any other details. Cool!
|
||||
pub fn print(self: Insect) void {
|
||||
switch (self) {
|
||||
inline else => |case| return case.print(),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
pub fn main() !void {
|
||||
var my_insects = [_]Insect{
|
||||
Insect{ .ant = Ant{ .still_alive = true } },
|
||||
Insect{ .bee = Bee{ .flowers_visited = 17 } },
|
||||
Insect{ .grasshopper = Grasshopper{ .distance_hopped = 32 }, },
|
||||
};
|
||||
|
||||
std.debug.print("Daily Insect Report:\n", .{});
|
||||
for (my_insects) |insect| {
|
||||
// Almost done! We want to print() each insect with a
|
||||
// single method call here.
|
||||
???
|
||||
}
|
||||
}
|
||||
|
||||
// Our print() method in the Insect union above demonstrates
|
||||
// something very similar to the object-oriented concept of an
|
||||
// abstract data type. That is, the Insect type doesn't contain
|
||||
// the underlying data, and the print() function doesn't
|
||||
// actually do the printing.
|
||||
//
|
||||
// The point of an interface is to support generic programming:
|
||||
// the ability to treat different things as if they were the
|
||||
// same to cut down on clutter and conceptual complexity.
|
||||
//
|
||||
// The Daily Insect Report doesn't need to worry about *which*
|
||||
// insects are in the report - they all print the same way via
|
||||
// the interface!
|
||||
//
|
||||
// Doctor Zoraptera loves it.
|
4
patches/patches/092_interfaces.patch
Normal file
4
patches/patches/092_interfaces.patch
Normal file
|
@ -0,0 +1,4 @@
|
|||
109c109
|
||||
< ???
|
||||
---
|
||||
> insect.print();
|
Loading…
Reference in a new issue