Thanks for the prompt response! Duck typing does make sure my code is correct, but I was hoping for something that gives a better dev experience, “communicate intent precisely” is part of Zig’s zen after all.
After more searching I found this post which inspired me to try moving the functions into Player’s fields instead:
pub const Player = struct {
drawAt: fn (x: u16, y: u16, char: u23) void,
playSound: fn (sound: Sound) void,
pub fn init(
comptime drawAt: fn (x: u16, y: u16, char: u23) void,
comptime playSound: fn (sound: Sound) void,
) @This() {
return .{ .drawAt = drawAt, .playSound = playSound };
}
// More code...
};
pub const Match = struct {
players: []Player,
// Mode code...
};
As far as I can tell, once compiled it’s functionally equivalent to everything above and IMO conveys intent better (drawAt
and playSound
are injected dependencies, why should they be baked in at type declaration?).