How to initialize array at runtime indexed by enum

I am trying to do the following:

TOKENS: [@typeInfo(TOKEN).@"enum".fields.len][:0]const u8 = undefined,

pub fn init() void {
    .TOKENS[TOKEN.IF] = "if";
}

But that does not work because the tag does not support indexing. I have tried several variations such as:

    .TOKENS[@as(usize, @intFromEnum(TOKEN.IF))] = "if";

Is this possible? If so, how can I use the enum to index an array?

TIA

See std.EnumArray. There’s also std.enums.directEnumArray

However, if you rename your enum fields, you’ll be able to use @tagName() to get an enum field name’s string, eliminating the need to store that info separately.

1 Like

Your issue is in trying to access .TOKENS, which AFAIK is not possible like that. You need to access it on a value of type @This(), usually passed as an argument. This works for me (changed to use standard capitalization convention:

tokens: [@typeInfo(Token).@"enum".fields.len][:0]const u8 = undefined,

pub fn init() void {
    var self: @This() = .{};
    self.tokens[@intCast(@intFromEnum(Token.@"if"))] = "if";
}

const Token = enum {
    @"if",
    @"fn",
};
1 Like

Not quite what I want. The values I store and use will not be the tag names.

This seems to be the best fit. The example is also clear. However the std.EnumArray is not clear for me. I will have to look for an example to check its aplicability.

Can you tell me what the advantage is of using these solutions? Please note I marked the other answer as a solution just because it answered my question “more directly”.

This works but I have a few newbie questions:

  1. Can you explain why I need the self in the function. Any reason why I should not declare and use a const self = @Self() at the module level and use that? (seems to work) I guess my real question is, do we need to instantiate the structure, that is then discarded.
  2. Why use a tag @"fn" instead of a simple fn? Is this a simple Zig idiom/convention?
  3. I have just realized, don’t I have to allocate the string that I use in the array?

Thanks for the answers.

  1. You can define tokens like var tokens: [@typeInfo(Token).@"enum".fields.len][:0]const u8 = undefined; instead, which will let you access it globally instead of as a field of @This().
  2. Same reason you used @"if", that syntax lets you use keywords as values / variable names. fn is a keyword in zig. I just wanted to have multiple values in my test since I didn’t want the backing int of the enum to be u0. Though it probably doesn’t matter.
  3. You don’t have to.
1 Like