maxwell
September 25, 2023, 11:18am
1
Hello,
I’m very new to zig and Im just trying to learn.
I’m trying to write a deck of cards program.
But I’ve encountered an error message that I don’t understand
In particular, I’m trying to write a struct bound function that returns the card’s name as a string. The struct is as follows.
const Card = struct {
suite: Suite,
value: Value,
pub fn name(self: Card) []u8 {
const v = switch (self.value) {
.number => |n| blk: {
if (n == 10) {
break :blk 'X';
} else {
break :blk n + '0';
}
},
.face => |f| blk: {
break :blk switch (f) {
.Jack => 'J',
.Queen => 'Q',
.King => 'K',
.Ace => 'A',
};
},
};
return v;
}
};
And the error message is
src/main.zig:24:28: error: value with comptime-only type 'comptime_int' depends on runtime control flow
break :blk switch (f) {
^~~~~~
src/main.zig:15:31: note: runtime control flow here
const v = switch (self.value) {
~~~~^~~~~~
I don’t understand what is supposed to be a compile-time value here.
Also, It doesn’t seem that simple to just cast an int to a string or u8
Thank you
Welcome to Zig as well as the forum!
Can you share more of your code? Specifically the definitions for Suite
and Value
// No type in declaration. The compiler will choose a fitting type for you.
// ↓
const v = switch...
All of your branches contain numbers (‘J’ for example is a number of type comptime_int
representing the ascii code of J)
So zig assumes you wanted:
const v: comptime_int = switch...
But a comptime_int
must be known at compile-time, thus an error is caused.
To fix this you can simply explicitly set the type:
const v: u8 = switch...
maxwell
September 25, 2023, 11:55am
4
Hi
Here you go:
const Suite = enum { Spades, Clubs, Harts, Diomands };
const Face = enum { Jack, Queen, King, Ace };
const Value = union(enum) {
number: u8,
face: Face,
};
maxwell
September 25, 2023, 11:56am
5
Thank you for the explanation, thats sorted it
Although the problem is solved, for the purpose of learning a bit more about Zig, I propose this example for this problem:
const std = @import("std");
const Suit = enum {
Clubs,
Diamonds,
Hearts,
Spades,
};
const Face = enum(u8) {
Ace = 1,
Two,
Three,
Four,
Five,
Six,
Seven,
Eight,
Nine,
Ten,
Jack,
Queen,
King,
};
const Card = struct {
face: Face,
suit: Suit,
pub fn format(self: Card, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
_ = try writer.print("{s} of {s} with value {}", .{
@tagName(self.face),
@tagName(self.suit),
@intFromEnum(self.face),
});
}
};
pub fn main() void {
const aos = Card{ .face = .Ace, .suit = .Spades };
std.debug.print("{}\n", .{aos});
const qoh = Card{ .face = .Queen, .suit = .Hearts };
std.debug.print("{}\n", .{qoh});
}
output:
Ace of Spades with value 1
Queen of Hearts with value 12
3 Likes
maxwell
September 25, 2023, 2:38pm
7
since your here can i ask one more thing
How can I loop over the possibilities for an enum?
I want to be able to iterate through the possible values of cards in order to create a deck, but
for (Face) |face| {
_ = face;
}
is not valid zig. ( Type ‘type’ is not indexble )
1 Like
@typeInfo (Type).Enum.fields will give you a list of all the possible values of an enum. There’s a shortcut: std.meta.fields(Type).
2 Likes
As @LucasSantos says, you can loop over the enum fields with std.meta.fields
but I believe it has to be an inline for
like this:
inline for (std.meta.fields(Face)) |face| {
// do something with face
}
The reason for this is that your dealing with types directly, and that can only be done at comptime. inline for
is a for
loop that runs at comptime.
2 Likes