-
Notifications
You must be signed in to change notification settings - Fork 29
initial draft for multi-level enums #117
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
object Animal: | ||
sealed trait Mammal extends Animal | ||
object Mammal: | ||
case object Dog extends Mammal |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to avoid getting into the weeds, because this is the wrong desugaring, its probably better to explain it in a set of recursive steps, where each case enum
becomes an enum
in the companion that extends the parent enum class (because an enum is a class not a sealed trait)
see the spec here: https://scala-lang.org/files/archive/spec/3.4/05-classes-and-objects.html#lowering-of-enum-definitions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the pointer!
I'll look into that and update the spec.
case enum Mammal: | ||
case Dog, Cat | ||
case enum Bird: | ||
case Sparrow, Pinguin |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also good to demonstrate how parameters work (e.g. case enum Bird(val call: String):
) and optional extends clauses
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also the rules of extends clauses, e.g. what class is allowed to be extended
also another point to address - enum constructor expression are widened to the parent enum, so which parent should a nested case widen to - as a rule it should be included |
|
||
- `Animal.values` returns all **leaf cases**: `[Dog, Cat, Sparrow, Pinguin, Fish]` | ||
- `Mammal.values` returns `[Dog, Cat]` | ||
- `Mammal.ordinal` and `Mammal.valueOf(...)` are also available |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe I missed it, but I think is not explicit how non-leaf ordinals are computed.
Would it be?
enum Animal: // No ordinal
case enum Mammal: // Ordinal 0
case Dog // Ordinal 0
case Cat // Ordinal 1
case enum Bird: // Ordinal 1
case Sparrow // Ordinal 2
case Pinguin // Ordinal 3
case Fish // Ordinal 2
If that is the case, I assume Mammal.fromOrdinal(...)
won't exist.
If it does exist, how would Bird.fromOrdinal(...)
work? Would it take "global ordinals" (2 for Sparrow and 3 for Penguin), or would it expect "local ordinals" (0 for Sparrow and 1 for Penguin)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, you didn't miss it. It's currently not specified.
Do Mammal
or Bird
, i.e. "sub-enums", need their own ordinal? Can we even instantiate them?
enum Animal: // No ordinal
case enum Mammal: // No ordinal
case Dog // Ordinal 0
case Cat // Ordinal 1
case enum Bird: // No ordinal
case Sparrow // Ordinal 2
case Pinguin // Ordinal 3
case Fish // Ordinal 4
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One really thorny question is what type gets inferred for term subcases:
val x = Animal.Mammal.Dog
What is the inferred type for x
? Choosing Dog.type
would be completely inconsistent with current enums. But then is it Animal
or Mammal
?
The SIP does not mention sub class cases at all. IMO that's missing.
content/multi-level-enums.md
Outdated
case Sparrow, Pinguin | ||
``` | ||
|
||
Each nested `enum` case defines a group of related subcases. The **nested enum is itself a valid case** of the parent enum, and its members are **also valid cases**, allowing full exhaustivity and pattern matching. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The nested enum is itself a valid case of the parent enum
This does not make sense to me. It's a subtype, sure. But it cannot be a valid (term) case of the parent enum while at the same time having several "sub-terms". A term must be unique.
The above syntax desugars to an enum tree with subtype relationships: | ||
|
||
```scala | ||
sealed trait Animal |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Enums are abstract class
es, not traits.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed.
content/multi-level-enums.md
Outdated
case Fish => false | ||
``` | ||
|
||
Matching on a **supercase** (e.g., `Mammal`) is shorthand for matching all its subcases. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This does not make sense. Matching on Mammal
itself already has meaning, which is to test if it is the Mammal
companion object
itself. That cannot be changed to means case Cat | Dog
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True, which is a shame. We can still match on supercase type though.
def laysEggs(a: Animal) = a match {
case _: Bird | Fish => true
case _ => false
}
Co-authored-by: Sébastien Doeraene <[email protected]>
Co-authored-by: Sébastien Doeraene <[email protected]>
A draft SIP for https://contributors.scala-lang.org/t/proposal-for-multi-level-enums/3344