I dunno if I'd consider having a dummy method on an interface as "elegant", but it does work. A trade-off of keeping the language very simple, for sure. What I really wish Go had was sum types, Rust style. That'd cover enumerations and more.
Compile-time safety for enumerations in Go
91–100 of 116 posts
Re: Compile-time safety for enumerations in Go
#92Earlier quoted context omitted.
> Casting as demonstrated in the example is normal and has to be expected. Can you give an example where someone has done similar casts accidentally? It seems like it would be hard to accidentally typo. That leaves malice, which seems difficult to defend against, in light of the kinds of system calls that are available to a program.
Sure, by parsing a string to a Color value.
I don't doubt that there are niches where such explicit type coercion patterns are common in Go and susceptible to mistakes, but I doubt usage of constant identifiers is such a niche.
Rust is currently the standard bearer for strong, static type safety, and it even has both the enum types and pattern matching construct which Go lacks. AFAIU, you can use unsafe{} Rust code to perform a similar type punning trick, successfully assigning an invalid value to an enum object. I don't know if Rust's code generator always inserts runtime validity checks in match statements on an enum value without a catchall/default case, but certainly it's possible for Rust code to have an explicit if/else chain that at compile time appears comprehensive but which would neither panic nor produce the expected behavior. Does that mean Rust programmers shouldn't rely on Rust's static typing, instead always adding explicit code to handle unknown/invalid enum values?
Maybe the assertion that Go code should have such checks is more reasonable than for Rust code, but you haven't explained how. At least to me, the simplest, minimal code to achieve the subversion in both Go and Rust seems similarly stilted and similarly unlikely to be written by mistake. (To be clear, the context of this subthread as I understand it assumes the interface method hack, the subversion of which requires the type punning.)
Re: Compile-time safety for enumerations in Go
#93This is not elegant. It also has overhead. Stick with the simple `const Red Color = "red"`, you're not gaining a lot by doing all these strange type contortions in Go. Seriously consider what you are protecting against, and whether it's an imagined bogeyman. "Oh but someone may try to cast arbitrary values to my package type" Okay but who is that going to hurt? You or them? Will they get hit with errors early on in t…
It's stuff that just creeps in. Enum values can come from outside (json, anything non-literal). Now you have to do validation, because the bad values parse and for sure exist at some stage in your program. It's not a bogeyman.
Re: Compile-time safety for enumerations in Go
#94I dunno if I'd consider having a dummy method on an interface as "elegant", but it does work. A trade-off of keeping the language very simple, for sure. What I really wish Go had was sum types, Rust style. That'd cover enumerations and more.
I hope Go will eventually get sum types but I hope they're better than Rust's where each variant is its own type.
Re: Compile-time safety for enumerations in Go
#95Earlier quoted context omitted.
> Casting as demonstrated in the example is normal and has to be expected. Can you give an example where someone has done similar casts accidentally? It seems like it would be hard to accidentally typo. That leaves malice, which seems difficult to defend against, in light of the kinds of system calls that are available to a program.
Sure, by parsing a string to a Color value.
Re: Compile-time safety for enumerations in Go
#96Another approach could be: package color type Color struct { val string } func (c Color) String() string { return c.val } var ( Red = Color{val: "red"} Green = Color{val: "green"} Blue = Color{val: "blue"} ) Since `val` is not exported, external packages cannot create arbitrary `Color`.
Re: Compile-time safety for enumerations in Go
#97Earlier quoted context omitted.
Sure, by parsing a string to a Color value.
The example given wasn't a simple cast of a value, and definitely not an implicit coercion. The example is more like C-style type punning where you explicitly cast a pointer to the value and then write through the dereferenced pointer. I don't doubt that there are niches where such explicit type coercion patterns are common in Go and susceptible to mistakes, but I doubt usage of constant identifiers is such a niche.…
Re: Compile-time safety for enumerations in Go
#98Earlier quoted context omitted.
You're not changing the underlying value of `color.Red`, you're changing the variable (in other words, `PrintColor(color.Red)` will still print `red`). If that's the point you're intending to make, then couldn't you make it more easily with this?: c := color.Red c = Color("orange") PrintColor(c)
> You're not changing the underlying value of `color.Red` Doesn't matter, the point is they're getting in a value which is not part of the defined set, demonstrating that this emulation is not actually typed-safe. > If that's the point you're intending to make, then couldn't you make it more easily with this?: cannot convert "orange" (untyped string constant) to type Color
Re: Compile-time safety for enumerations in Go
#99Go doesn’t have type-safe enums in the language? That’s wild, even C compilers have this feature now (optionally), and then there’s Rust/Swift’s capabilities.
Welcome to Go. “Wait, Go doesnt have X?” I’m convinced its an incomplete language masquerading as a simple one.
Re: Compile-time safety for enumerations in Go
#100Here is an issue tracking a possible fix to this: https://github.com/golang/go/issues/19412
As stated in that proposal, the interaction between what people want from “enums,” “discriminated unions,” “sum types,” (as well as “optional values” and “nil safety”) and fundamental Go tenets like zero values, make this a tough sell, which is very likely to make no one happy.