ziglang / zig

General-purpose programming language and toolchain for maintaining robust, optimal, and reusable software.
https://ziglang.org
MIT License
34.51k stars 2.52k forks source link

Allow matching against a range of enum values inside a switch statement #4268

Open momumi opened 4 years ago

momumi commented 4 years ago

When using a switch statement to match against enums, it would be nice to be able to match against a range of enum values eg:

const warn = @import("std").debug.warn;

const Key = enum {
    A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
    _0, _1, _2, _3, _4, _5, _6, _7, _8, _9,
    SpaceBar,
};

pub fn main() anyerror!void {
    var key = Key.M;

    switch (key) {
        Key.A  ... Key.Z   => warn("alpha: {}", .{key}),
        Key._0 ... Key._9  => warn("number: {}", .{key}),
        Key.SpaceBar       => warn("other: {}", .{key}),
    }
}

Currently you can get this to work using @enumToInt like this:

    // this works because zig implicitly uses a tag of u6 to represent Key
    switch (@enumToInt(key)) {
        @enumToInt(Key.A) ...@enumToInt(Key.Z)  => warn("alpha: {}\n", .{key}),
        @enumToInt(Key._0)...@enumToInt(Key._9) => warn("number: {}\n", .{key}),
        @enumToInt(Key.SpaceBar)                => warn("other: {}\n", .{key}),
        else => unreachable,
    }

But this is not perfect though because I need to add else => unreachable, hence I won't get error messages if I update the enum and forget to add the new values to the switch statement.

raulgrell commented 4 years ago

Adding to this proposal, the payload should contain a subset of the enum values such that it can be checked exhaustively:

const X = enum {A, B, C, D, E};
switch(x) {
    .A, .E => |vowel| switch(vowel) {
        .A => {},
        else => {} //ok, handles other cases
    },
    .B .. .D => |cons| switch (cons) {
        .B => {},
        .D => {}, 
    } //  error, doesnt handle .C
}
Sobeston commented 4 years ago

I think that this could result in problems in many areas of code. While the example of Key.A ... Key.Z makes sense, something like Clubs ... Diamonds does not as there is no ordering to playing card suits. I think that this is the case for most enums.

This could result in poor practices and fragile code - a maintainer of a package/library no longer has to just worry about the presence of enum values, but also the ordering.

bibo38 commented 1 year ago

This issue can be closed in favor of #15556 , which also contains a counter proposal