Live data from Hacker News

Compile-time safety for enumerations in Go

vladimir.varank.in

31–40 of 116 posts

Re: Compile-time safety for enumerations in Go

#31

> Go’s type system allows preventing both issues in a rather elegant way. Proper enums would be elegant, not this.

Some way to define a closed set of values anyway. It doesn't even need to be classic-style sum types, for instance as support for generics Go introduced support for union types (I don't think they have a name?) e.g. type Foo interface { A | B | C } and the interface type is the union of those type-sets. Such interfaces can not currently be used outside of type constraints, but if that is relaxed, and type switches ar…

Agreed. A slight wart is that default initialization would require either boxing or a somewhat arbitrary decision about which variant should be the default. So if you have e.g.

    var foo interface{ A | B }
then foo either has to be boxed (so the default value is a nil interface) or unboxed and arbitrarily initialized as an A or a B.

Re: Compile-time safety for enumerations in Go

#32
This 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 the development lifecycle if they do something silly like this? Are you actually going through all these lengths for nothing?

Re: Compile-time safety for enumerations in Go

#33
post #32

This 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…

What overhead is there at runtime?

Re: Compile-time safety for enumerations in Go

#34
post #30
post #29

Earlier quoted context omitted.

The article is titled "Compile-time safety for enumerations in Go" but my example demonstrates that this is not the case.

The counter point is that this is like arguing that an article about safe knife skills are silly, because you can still just stab yourself?

I'm not sure how that's comparable. Compile-time type safety is a boolean thing, you either have it or you don't. If you have it, then my example shouldn't compile. But it does compile, so you don't have it.

Re: Compile-time safety for enumerations in Go

#35
post #33
post #32

This 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…

What overhead is there at runtime?

Casting a value to an interface forces it to be allocated on the heap.

Re: Compile-time safety for enumerations in Go

#36
post #33
post #32

This 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…

What overhead is there at runtime?

Interfaces are both allocations and function-call indirection, and I think they also always move their data to the heap.

Which is almost always trivial except when it isn't.

Re: Compile-time safety for enumerations in Go

#38
post #31

Earlier quoted context omitted.

Some way to define a closed set of values anyway. It doesn't even need to be classic-style sum types, for instance as support for generics Go introduced support for union types (I don't think they have a name?) e.g. type Foo interface { A | B | C } and the interface type is the union of those type-sets. Such interfaces can not currently be used outside of type constraints, but if that is relaxed, and type switches ar…

Agreed. A slight wart is that default initialization would require either boxing or a somewhat arbitrary decision about which variant should be the default. So if you have e.g. var foo interface{ A | B } then foo either has to be boxed (so the default value is a nil interface) or unboxed and arbitrarily initialized as an A or a B.

To me it would make sense that this be implemented as a normal interface at least initially, it would reuse all the existing bits of the language as is. Note that whether an interface boxes depends on escaping.

I don't see how unboxing would have to be "arbitrarily initialized as an A or a B" either. Even with a novel bespoke implementation you still need a discriminant between the two nested. You could keep a nil default by reserving the zero discriminant for that purpose.

Re: Compile-time safety for enumerations in Go

#39

I would be interested to read bug reports from people who thought they had a complete enumeration but learned in production that their enumeration was incomplete. I've never seen it myself.

This is relatively common with naive int / string to enum type conversions, especially if the int or string are given as input from an RPC mechanism of some sort.

This type of pattern can be used to force other developers to check if the value is garbage before calling $BUSINESS_LOGIC that uses the enum

Post reply on HN