I read quite some stuff about packed unions here and there.
Two questions I have.
Will this in the future be forbidden?
const U = packed union {
x: u3,
y: u2,
}
Will in the future comparison with == be possible like with packed structs?
Packed unions don’t have tags, so comparing them is undefined, since you can’t differentiate between which field is active which itself mean some bits are undefined.
You can use == if you wrap it in a packed struct, the idea is you can add a tag that way, though I don’t think it checks if there actually is any other field than the union.
The exact binary size is known. But I guess it is unsafe.
It is quite inconvenient that also the std.mem functions with a compare / find do not work.
I had to write some insane code to compare two structs.
@cryptocode yes i know… just confused about what’s the future (if any) of the packed union.
what’s the code? maybe there’s a better approach
I use a few enums like this:
pub const Square = packed union
{
const Enum = {a1, a2, a3, a4..... h8};
e: Enum,
u: u6,
}
The same trick for Color, Piece, PieceType etc.
This makes it convenient to index, compare or increase or decrease the u part instead of having to use @intFromEnum or @enumFromInt all over the place.
When there is a
board: [64]Piece I have to do this to compare
// ....
// Types not directly binary comparable with Zig std.
inline for (0..64) |i| if (self.board[i].u != other.board[i].u) return false;
// ...
see here
In my feeling comparing packed unions should be == and != able exactly the same as packed structs.
I’m not sure I understand what you are going for with the unions, but it seems like you are going through a lot of trouble using packed unions when you could be using @intFromEnum(val) and std.EnumArray. something like:
pub const PieceType = enum(u3) {
no_piecetype = 0,
pawn = 1,
knight = 2,
bishop = 3,
rook = 4,
queen = 5,
king = 6,
pub const all: [6]PieceType = .{ .pawn, .knight, .bishop, .rook, .queen, .king };
pub const values: std.EnumArray(PieceType, Value) = .init(.{
.no_piecetype = 0,
.pawn = 100,
.knight = 305,
.bishop = 333,
.rook = 563,
.queen = 950,
.king = 0,
};
};
also; check out this post which has a good demo of “optional” enums: https://ziglang.org/devlog/2024/#2024-11-04
I know about the existance of EnumArray. I will test if the speed is equal to a raw array.
Try and add -8 to a Square that way…
That is a lot of trouble.
Now I can do just
var sq: Square = Square.E4.
sq.u -= 8;
EnumArray will just give you lookup in memory compared to union which is just nope. The actual way to do it is with @enumFromInt and @intFromEnum which are also nope. If you need some more convenience add methods to enum.
So it will look like self.board[i].u() != other.board[i].u().
EDIT: Hmm no self.board[i] != other.board[i] since it just enum comparison. But for greater/less it would look like so self.board[i].u() < other.board[i].u()
if these are indeed no-operations I will indeed check if my code gets more convenient.
I am not really satisfied with the packed unions right now… Lots of side-effects for callsite too…
Thanks!
EDIT: for now I stay with my “inconvenient” code. A few rewrites using @enum conversions slowed down incredibly. I am not at all sure if I did something wrong so I leave this experiment for later.