zig icon indicating copy to clipboard operation
zig copied to clipboard

Improve `std.StaticStringMap.initComptime`

Open clickingbuttons opened this issue 1 year ago • 8 comments

Status quo uses an anonymous struct of struct{ []const u8, T }:

const NameMap = std.StaticStringMap(@This()).initComptime(.{
    .{ "c89", .c89 },
    .{ "c90", .c89 },
    .{ "iso9899:1990", .c89 },
});

I propose a more map-like anonymous struct:

const NameMap = std.StaticStringMap(@This()).initComptime(.{
    .c89 = .c89,
    .c90 = .c89,
    .@"iso9899:1990" = .c89,
});

I don't think this is a design issue as long as Zig identifiers can be any arbitrary bytes.

Edit: This would also prevent accidentally initializing the same key twice at compile time.

const NameMap = std.StaticStringMap(@This()).initComptime(.{
    .{ "c89", .c89 },
    .{ "c89", .c90 },
});

clickingbuttons avatar May 10 '24 20:05 clickingbuttons

This change would make building the key value list pragmatically much more complicated, you would need to use @Type.

leecannon avatar May 10 '24 22:05 leecannon

The reason why initComptime takes in a slice of tuples is so you construct the list at comptime:

const Enum = ErrorEnum(ErrorSet);
const error_to_enum = error_to_enum: {
    const ErrorEnumItem = std.meta.Tuple(&[_]type{ []const u8, Enum });
    comptime var error_to_enum_list: [es.len]ErrorEnumItem = undefined;
    inline for (0.., es) |i, err| {
        error_to_enum_list[i] = .{
            err.name,
            @field(Enum, err.name),
        };
    }

    break :error_to_enum std.StaticStringMap(Enum).initComptime(&error_to_enum_list);
};

Pyrolistical avatar May 11 '24 03:05 Pyrolistical

My real issue with the current API is that nothing stops you from passing multiple tuples with the same key. What do you think the following code prints?

pub fn main() !void {
    const Foo = enum { a, b };
    const NameMap = std.StaticStringMap(Foo).initComptime(.{
        .{ "c89", .b },
        .{ "c89", .a },
    });

    std.debug.print("{}\n", .{ NameMap.get("c89").? });
}

The answer may surprise you. This kind of mistake is a common copy-paste error.

This change would make building the key value list pragmatically much more complicated, you would need to use @Type.

No usage in the stdlib builds a key value list at comptime. Every usage is truly a static string map. I consider @Pyrolistical's use case an exception rather than the norm.

If you really want convenient support for building a list from a comptime var, there could be a initComptimeList that builds a @Type and correctly errors on duplicate keys.

clickingbuttons avatar May 13 '24 17:05 clickingbuttons

the compiler not doing it, doesn't mean its not done out in the wild. I would expect the example above to compile error (through the use of a comptime assertion)

nektro avatar May 13 '24 20:05 nektro

@clickingbuttons here it usage in zig-gamedev, of which I wrote: https://github.com/zig-gamedev/zig-gamedev/blob/09cb2d2bd814f6856f437ef2c9cb051abb068a54/libs/zgui/src/gui.zig#L1647-L1685

Pyrolistical avatar May 13 '24 20:05 Pyrolistical

No usage in the stdlib builds a key value list at comptime.

That's just not true https://github.com/ziglang/zig/blob/6a65561e3e5f82f126ec4795e5cd9c07392b457b/lib/std/meta.zig#L25-L33

silversquirl avatar May 14 '24 05:05 silversquirl

You're correct @silversquirl, I missed that one! My point still stands that the majority of usage, and I'd argue the intended usage is passing a static map-like structure rather than a built list.

clickingbuttons avatar May 14 '24 19:05 clickingbuttons

I don't think this is a design issue as long as Zig identifiers can be any arbitrary bytes.

there are two current limits on identifiers that i am aware of:

initComptime(.{
    .@"" = 1,     // identifier cannot be empty
    .@"\x00" = 2, // identifier cannot contain null bytes
});

paperclover avatar May 22 '24 23:05 paperclover

I think @paperdave 's example is enough of a reason not make a map API the default.

I'll open a separate issue to make duplicate keys a comptime error.

clickingbuttons avatar May 24 '24 03:05 clickingbuttons