4 ms·
Setting aside the full enum API, as well as certain optimizations, this is a rough equivalent of the enum I gave: public class Day extends Enum<Day> {
by kbolino 1y ago
Setting aside the full enum API, as well as certain optimizations, this is a rough equivalent of the enum I gave:
public class Day extends Enum<Day> {
private int _ordinal;
private Day(int ordinal) { this._ordinal = ordinal; }
public int ordinal() { return this._ordinal; }
public static final Day SUNDAY = new Day(0);
// ...
public static final Day SATURDAY = new Day(6);
}
with the added constraint that the Day constructor cannot be invoked by reflection, and the static instances shown herein can be used in a switch statement (which may reduce them to their ordinals to simplify the jump table). Each instance is ultimately a pointer, so yes it could be pulled from a sort of RNG (the allocator). As I said they are probably in an array, so it's likely that the addresses of each variant start from some semi-random base but then increase by a fixed amount (the size of a Day object). A variable of type Day stores the pointer, not the ordinal.
Now, it really seems to be in the weeds of pedantry when you start talking about discriminated unions that have only discriminants and no payload. Taking from your examples, the key point is that a Foo is not a Bar and is also not an int. Regardless of whether the variants are distinct or overlapping in their ordinals, they are not interchangeable with each other or with machine-sized integers.
- 9rx 1y ago> this is a rough equivalent of the enum I gave Yes, this echos what I stated earlier: "An enum is conceptually the same as you manually typing 1, 2, 3, ... as constants, except the compiler generates the numbers for you automatically" Nice to see that your understanding is growing. > Taking from your examples, the key point is that a Foo is not a Bar. I'm not sure that's a useful point. Nobody thinks class Foo {} class Bar {} ...are treated as being the same in Java, or, well any language that allows defining types of that nature. That is even the case in Go! type Foo int type Bar int const f Foo = iota const b Bar = f // compiler error on mismatched types But what is significant to the discussion about enums is the value that drives the inner union of the class. As in, the numbers that rest beneath SUNDAY, MONDAY, TUESDAY, etc. That's the enum portion.
- kbolino 1y agoI don't understand anything more now than I did at the start. It is clear we are talking past each other. The values of Day are {SUNDAY, ..., SATURDAY} not {0, ..., 6}. We can, of course, establish a 1:1 mapping between those two sets, and the API provides a convenient forward mapping through the ordinal method and a somewhat less convenient reverse mapping through the values static method. However, at runtime, instances of Day are pointers not numbers, and ints outside the range [0, 6] will never be returned by the ordinal method and will cause IndexOutOfBoundsException if used like Day.values()[ordinal]. Tying back to purpose of this thread, Go cannot deliver the same guarantee. Even if we define type Day int const ( Sunday Day = iota // ... Saturday ) then we can always construct Day(-1) or Day(7) and we must consider them in a switch statement. It is also trivial to cast to another "enum" type in Go, even if the variant doesn't exist on the other side. This sealed, nonconvertible nature of Java enums makes them "true" enums, which you can call tag-only discriminated unions or whatever if you want, but no such thing exists in Go. In fact, it is not even possible to directly adapt the Java approach, since sealed types of any kind, including structs, are impossible thanks to new(T) being allowed for all types T.
- 9rx 1y ago> This sealed, nonconvertible nature of Java enums makes them "true" enums, which you can call tag-only discriminated unions or whatever if you want, and no such thing exists in Go. It is no secret that Go has a limited type system. In fact, upon release it was explicitly stated that their goal was for it to be a "dynamically-typed language with statically-typed performance", meaning that what limited type system it does have there only to support the performance goals. You'd have to be completely out to lunch while also living under a rock to think that Go has "advanced" types. But, as before, enums are values. It is not clear why you want to keep going back to talking about type systems. That is an entirely different subject. It may be an interesting one, but off-topic as it pertains to this discussion specifically about enums, and especially not useful when talking in the context of Go which it isn't really intended to be a statically-typed language in the first place.