Zig NEWS

Discussion on: Easy Interfaces with Zig 0.10.0

Collapse
 
tensorush profile image
Jora Trush

Thanks for the post! Found a way to have a mutable version, too:

const Cat = struct {
    hp: usize,

    pub fn eat(self: *Animal) void {
        self.cat.hp += 1;
    }
};

const Animal = union(enum) {
    cat: Cat,
    dog: Dog,

    pub fn eat(self: *Animal) void {
        switch (self.*) {
            inline else => |case| @TypeOf(case).eat(self),
        }
    }
};
Enter fullscreen mode Exit fullscreen mode
Collapse
 
kristoff profile image
Loris Cro • Edited

Spoke with Spex and Andrew and they confirmed that doing switch (self.*) does not create a copy, so you can do this:


const Cat = struct {
    hp: usize,

    pub fn eat(self: *Cat) void {
        self.hp += 1;
    }
};

const Animal = union(enum) {
    cat: Cat,
    dog: Dog,

    pub fn eat(self: *Animal) void {
        switch (self.*) {
            inline else => |*case| case.eat(),
        }
    }
};
Enter fullscreen mode Exit fullscreen mode

Diff:

  1. eat now accepts a *Cat, not a *Animal
  2. the switch case is now capturing |*case| and calling the function normally

This would not work if self.* created a copy, but since it never does, it's fine.

Collapse
 
kfird214 profile image
kfir • Edited

If you have *Cat, why would you need
self.cat.hp += 1;
and not:
self.hp += 1;

Thread Thread
 
kristoff profile image
Loris Cro

oh, I forgot to update that line from the original code by Zhora.

I've fixed it now, thank you.

Collapse
 
tensorush profile image
Jora Trush

That's neat! I'll try it, thanks ;)

Collapse
 
kristoff profile image
Loris Cro • Edited

Oof, this is very annoying and error prone, I tried to think about it for a moment but I don't see a better way of doing that. Thank you for bringing that usecase to my attention.