> We use enums heavily to force devs who use our code into good choices
Beware, tho, that with many languages today you’re not really doing that even when they advertise enums e.g. in both C# and C++, enums are not type-safe (not even `enum class`). Iota is, at least, a fair acknowledgement of that.
> with a FromString() function
That seems like way a step too far, is there any such “default method” today? And I don’t think Go has any sort of return-type overloading does it?
Really not sure what you're talking about. If you use enums in a real language like Swift, Kotlin, Rust, etc., you can only construct the values of the enum. There are no ways to get around it.
> I am likewise unsure how a language could get enums wrong, even after reading your post.
By allowing any value of the underlying type, even if they were not values of the enum. The language most famous for this is obviously C:
enum foo { A, B, C };
int main() {
enum foo x = A;
printf("%d\n", x);
enum foo y = 42;
printf("%d\n", y);
}
This will print `0` and `42` (https://godbolt.org/z/Yq8qq5bzW), because C considers enums to be integral types and will thus implicitly convert to or from them. And as you can see from the link, there is no warning under `-Wall`. Clang will warn with `-Wassign-enum` (which is included in `-Weverything`), I don't think there's any way to make gcc complain about this.
Now you might argue that this is C so obviously it fucks this up, however that C does this leads to further issues:
- For compatibility with C, C# enums have the same property. I don't know about you, but that surprised me a great deal since Java has type-safe enums (even if they're not sum types).
- Even more so, C++ added `enum class` in C++11, and obviously has inherited C's enums, but enum class still is not type safe, afaik the differences are that `enum class` is scoped (so in the snippet above you'd need `foo::A`) and it's not implicitly convertible with the underlying type. But it's still explicitly convertible (via a cast or list initialisation), meaning you can't assume a caller will remain within the enum.
This is only a problem in languages that don't support checked type safe enums / discriminated unions, but this whole thread was started to request that feature. I don't get the point of your comments unless it's to state "be careful or they'll do it wrong"... which is obvious and already acknowledged several times in this thread.
Every time I see discussion about go and enums there are people who are referencing these mythical C-like enums that had never existed. It's some sort of constructed memory. And I'm sure there are languages that do enums "properly", but it's always C/C++ that is referenced.
Ada does them well. They have attributes that allow for converting to and from integers and strings [1], and case statements have to be exhaustive or use a default "others" clause.
Beware, tho, that with many languages today you’re not really doing that even when they advertise enums e.g. in both C# and C++, enums are not type-safe (not even `enum class`). Iota is, at least, a fair acknowledgement of that.
> with a FromString() function
That seems like way a step too far, is there any such “default method” today? And I don’t think Go has any sort of return-type overloading does it?