Sometimes I am getting very tired of my enums and packed unions in my chessprogram.
Packed unions are my attempt to have both an enum as well as the raw value and I have a lot of them.
Sometimes more convenient to code and sometimes not.
In Zig packed unions are not ‘comparable’ with std.mem.eql when having an array of them, which is another pain.
Instead of having this:
pub const Piece = packed union {
pub const Enum = enum(u4) {
white_pawn = 0, // etc.
}
/// The enum value.
e: Enum,
/// The numeric value.
u: u4,
}
I sometimes think of just this:
pub const Piece = u4;
The same I have for Square, Color, PieceType etc.
Do people experience the same pain / doubt when choosing the encoding of your little entities?
Typed or raw?
I was originally hooked on packed structs, but I find myself using manual bitmasks a lot more recently, just like I’d have done in other languages. I mostly do it because I find it easier to compose the values that way.
1 Like
I found myself leaning away from [n]Rect and towards unstructured separate arrays. I seem to recall an article from Andrew which touted some performance benefits, but I cant recall the details now.
For bit masks I’m still in love with packed struct(u32) or whatever new name it has this month. And for a couple data structures I’ve ended up with some raw Global Assembly, although that was triggered my some unaligned struct member access I couldnt get to the bottom of.
I havent found much use for union thus far, coming from higher level languages they are not really in my mental toolbox, so I tend to use a const int for the value, and create switch based lookup tables for field names for debug, or other value interpretations. Maybe I’ll be doing the opposite and leaning more towards Piece now that I see some value to it 
You could use the @intFromEnum and @enumFromInt builtins to convert between enums and their numeric value, and then you don’t need the union. If you don’t use the builtis because they’re a little verbose, you could create methods (that call the builtins) for get/set of the raw value.
Sorry, I’m not following you. How are the manual bitmasks composed?
By using bitwise OR operations. I find it easier to do flags | another_flag than making a copy of flags and then setting flags_copy.another_flag = true.
1 Like
I am always torn between the two. It often feels like there is situations where one “feels” much better than the other, even within the same enum type, just depending on the situation.
I often wish there were better ergonomics using masks and setting/unsetting/comparing multiple bit values in one shot without all the extra verbosity, though I admit I don’t have much in the ideas of how that would be accomplished using the current design. The ability to transparently use bitwise operators on packed structs might be nice, but not every packed struct represents C-style bitmask, so it might cause more problems than it solves.