That isn’t the real code you are running, orientation and direction don’t even have declared types.
Why do you want to use comptime fields, what is your goal?
I would expect the Iterator to be a function that takes orientation and direction as comptime parameters and returns a struct type, then those fields can be regular fields orientation: Orientation.
If I remember correctly comptime fields only exist for anonymous structs and tuples. You generally shouldn’t use them yourself.
You can achieve the same thing here with a comptime Iterator type:
fn iterator(comptime orientation: Orientation, comptime direction: Direction) Iterator(oerientation, direction) {
return .{...etc.};
}
fn Iterator(comptime orientation: Orientation, comptime direction: Direction) type {
return struct {
board: *Board,
// and some more
};
}
This is some more code.
The funny thing is that the Board.letter_iterator() function works when I call it with the default values.
Otherwise I get:
error: value stored in comptime field does not match the default value of the field
So what is the big trick (if any) to initialize this BoardLetter iterator with other than the default values?
I think it is best to approach generic types like this in reverse until you are familiar enough with them, to write the generic version right away.
So my suggestion would be to first write a non generic version that hardcodes the comptime parameters as two constants.
Then see how this differs to a second one with the constants changed.
Then do the step of turning it into a generic type function.
It also seems like there is a misconception somewhere.
When you have a function that has comptime types and returns a type (in this case a struct that implements an iterator) this struct type already has access to those comptime parameters, there is no need to store those as fields.
Think what it means for a type to have comptime and non-comptime fields. For instance, comptime_int doesn’t have a well-defined size, how can a struct contain one? comptime fields are just syntactic sugar that allows you to access a comptime value using the . syntax. The actual value can’t coexist with normal runtime data. Therefore, comptime fields are read-only. When assigning to them, you must guarantee that you are assigning the same value that they already contain. All of this dance just exists for the purposes of generic programming. You could achieve the same thing using a const declaration in the type, but then, when doing generic functions you’d have to create two versions, one that expects the data to be a field, and one that expects it to be a declaration.
What you want is a generic type:
// still does not compile
var it = board.letter_iterator(112, .Horizontal, .Forwards);
src\main.zig:87:19: error: unable to resolve comptime value
var it = board.letter_iterator(112, .Horizontal, .Forwards);
~~~~~^~~~~~~~~~~~~~~~
src\scrabble.zig:382:130: note: expression is evaluated at comptime because the function returns a comptime-only type 'type'
pub fn letter_iterator(self: *const Board, square: Square, comptime orientation: Orientation, comptime direction: Direction) type
You can’t use type there instead use BoardLetterIterator(orientation, direction).
Why doesn’t this work?
Because Zig only has limited support for type inference / you can use type when you are returning a type, but here you are actually returning a value of a specific type.