4 ms·
Java has true enums that are neither fancy integers nor discriminated unions. The following is not a list of integers: public enum Day { SUNDAY, MO
by kbolino 1y ago
Java has true enums that are neither fancy integers nor discriminated unions. The following is not a list of integers:
public enum Day {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
THURSDAY, FRIDAY, SATURDAY
}
To use this enum, you typically declare a variable of type Day, which is a subclass of Enum, itself a subclass of Object, which cannot be cast to or from int. If a variable is typed as Day, then it can only take one of these variants (or null). Even though the Day class does have an ordinal() method, and you can look up the variants by ordinal, you cannot represent Day(7) or Day(-1) in any way, shape, or form. This sealed set of variants is guaranteed by the language and runtime (*). Each variant, like SUNDAY, is an instance of class Day, and not a mere integer. You can attach additional methods to the Day class, and those methods do not need to anticipate any other variants than the ones you define. Indeed, enums are sometimes used with a single variant, typically called INSTANCE, to make true singletons.
* = There is a caveat here, which is that the sealed set of variants can differ between compile-time (what's in a .java file) and runtime (what's in a .class file) but this only happens when you mismatch your dependency versions. Rather importantly, the resolution of enum variants by the classloader is based on their name and not their ordinal, so even if the runtime class differs from the compile-time source, Day.MONDAY will never be turned into a differently named variant.
- 9rx 1y ago> The following is not a list of integers Then I am not sure how you think it is an enum? What defines an enum, literally by dictionary definition, is numbering. It is hilarious to me that when enum is used in the context of looping over an array, everyone understands that it represents the index of the element. But when it comes to an enum in a language, all of a sudden some start to think it is magically something else? But the whole reason it is called an enum is because it is produced by the order index of an AST/other intermediate representation node. The very same thing! While I haven't looked closely at how Java implements the feature of which you speak, I'd be surprised if it isn't more or less the same as how Rust does it under the hood. As in using a union with an enumerator producing the discriminant. In this case it would be a tag-only union, but that distinction is of little consequence for the purposes of this discussion. That there is an `ordinal` method pretty much confirms that suspicion (and defies your claim). > you cannot represent Day(7) or Day(-1) in any way, shape, or form. While that is true, that's a feature of the type system. This is a half-assed attempt at sum types. Enums, on the other hand, are values. An enum is conceptually the same as you manually typing 1, 2, 3, ... as constants, except the compiler generates the numbers for you automatically, which is what is happening in your example. The enum is returned by `ordinal`, like you said. Same as calling std::mem::discriminant in Rust like we already discussed in a sibling thread.
- kbolino 1y agoThe existence of the ordinal method reveals nothing except that the ordinal exists. It can be (and is) simply a field on each Day object, not an index into anything (though the Day objects are probably stored in an array, this is not required by any property of the system). Day.SUNDAY is ultimately a pointer, not an int. It is also a symbolically resolved pointer, so it will never become Day.MONDAY even if I reorder the variants so that their ordinals are swapped. The ordinal is not a discriminant. You seem to be trivializing the type system. This property is not imagined solely by the compiler, it is carried through the language and runtime and cannot be violated (outside of bugs or unsafe code). Go has nothing like this. If you choose to call this "not an enum", that is certainly your idiosyncratic prerogative, but that doesn't make for very interesting discussion. Even though I agree that discriminated unions aren't enums and am somewhat annoyed by Rust's overloading of the term, this is not that.
- 9rx 1y ago> The existence of the ordinal method reveals nothing except that the ordinal exists. It strongly suggests that implementation is a discriminated union, just like Rust. Again, it is tag-only in this case, where Rust allows also attaching payload, but that's still a type of discriminated union. That it is a set of integers – contrary to the claim made earlier – combined with you explaining how the compiler treats it like a discriminated union — as in that there are type checks against the union state, that does reveal that it couldn't be anything other than a discriminated union that is effectively identical to what we find in Rust, along with many other languages these days. > It can be (and is) simply a field on each Day object, not an index into anything So...? Enum is not staunch in exactly where the number comes from; it simply needs to number something. Indices are convenient, though, and I am not sure why you would use anything else? That doesn't necessarily mean the index will start where you think it should, of course. For example, enum Foo { A, B, C } enum Bar { X, Y, Z } In some languages, the indices might "reset" for each enum [A=0, B=1, C=2, X=0, Y=1, Z=2], while in other languages it might "count from the top" [A=0, B=1, C=2, X=3, Y=4, Z=5]. But, meaningless differences aside, where else is the number going to come from? Using a random number generator would be silly. But, humour us, how does Java produce its enums and why doesn't it use indices for that? Moreover, why did they choose to use the word `ordinal` for the method name when that literally expresses that it is the positional index?