You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I had a lingering unease that the rules for enums were too complex, and the syntax too cumbersome.
I now think I have found a way to simplify things considerably. The key was to take away one
capabilitiy: that cases can have bodies which can define members. Arguably, if we choose
an ADT decompositon of a problem it's good style to write all methods using pattern matching instead
of overriding individual cases. So this removes an unnecessary choice. What's more, once
we have eliminated case bodies we also have eliminated scope confusion. All that remains
are the case parameters and extends clause. Extends clauses of cases can be handled like supercalls
in constructors: I.e. the enclosing enum class is not visible for them.
This means we can treat enums unequivocally as classes. They can have methods and other statements
just like other classes can. Cases in enums are seen as a form of constructors. We do not
need a distinction between enum class and enum object anymore. Enums can have
companion objects just like normal classes can, of course.
This also means that type parameters of enums scope naturally over cases, just like they scope
over secondary constructors. We do not need to repeat them in cases anymore, which is a huge relief.
This first commit changes the syntax and docs. It still needs to be implemented.
Copy file name to clipboardExpand all lines: docs/docs/reference/enums/desugarEnums.md
+64-69Lines changed: 64 additions & 69 deletions
Original file line number
Diff line number
Diff line change
@@ -3,111 +3,109 @@ layout: doc-page
3
3
title: "Translation of Enums and ADTs"
4
4
---
5
5
6
-
The compiler expands enum classes and cases to code that only uses
6
+
The compiler expands enums and their cases to code that only uses
7
7
Scala's other language features. As such, enums in Scala are
8
8
convenient _syntactic sugar_, but they are not essential to understand
9
9
Scala's core.
10
10
11
11
We now explain the expansion of enums in detail. First,
12
12
some terminology and notational conventions:
13
13
14
-
- We use `E` as a name of an enum class, and `C` as a name of an enum case that appears in the companion object of `E`.
15
-
- We use `<...>` for syntactic constructs that in some circumstances might be empty. For instance `<body>` represents either the body of a case between `{...}` or nothing at all.
14
+
- We use `E` as a name of an enum, and `C` as a name of a case that appears in `E`.
15
+
- We use `<...>` for syntactic constructs that in some circumstances might be empty. For instance,
16
+
`<value-params>` represents one or more a parameter lists `(...)` or nothing at all.
16
17
17
18
- Enum cases fall into three categories:
18
19
19
20
-_Class cases_ are those cases that are parameterized, either with a type parameter section `[...]` or with one or more (possibly empty) parameter sections `(...)`.
20
-
-_Simple cases_ are cases of a non-generic enum class that have neither parameters nor an extends clause or body. That is, they consist of a name only.
21
+
-_Simple cases_ are cases of a non-generic enum that have neither parameters nor an extends clause or body. That is, they consist of a name only.
21
22
-_Value cases_ are all cases that do not have a parameter section but that do have a (possibly generated) extends clause and/or a body.
22
23
23
24
Simple cases and value cases are collectively called _singleton cases_.
24
25
25
26
The desugaring rules imply that class cases are mapped to case classes, and singleton cases are mapped to `val` definitions.
26
27
27
-
There are eight desugaring rules. Rules (1) and (2) desugar enums and
28
-
enum classes. Rules (3) and (4) define extends clauses for cases that
29
-
are missing them. Rules (5 - 7) define how such expanded cases map
30
-
into case classes, case objects or vals. Finally, rule (8) expands
31
-
comma separated simple cases into a sequence of cases.
28
+
There are eight desugaring rules. Rule (1) desugar enum definitions. Rules
29
+
(2) and (3) desugar simple cases. Rules (4) to (6) define extends clauses for cases that
30
+
are missing them. Rules (7) and (8) define how such cases with extends clauses
31
+
map into case classes or vals.
32
32
33
33
1. An `enum` definition
34
34
35
-
enum E ... { <cases> }
35
+
enum E ... { <defs> <cases> }
36
36
37
-
expands to an enum class and a companion object
37
+
expands to a `sealed``abstract` class that extends the `scala.Enum` trait and
38
+
an associated companion object that contains the defined cases, expanded according
39
+
to rules (2 - 8).
38
40
39
-
enum class E ...
40
-
object E { <cases> }
41
+
sealed abstract class E ... extends <parents> with scala.Enum { <defs> }
42
+
object E { <cases> }
41
43
42
-
2.An enum class definition
44
+
2.A simple case consisting of a comma-separated list of enum names
43
45
44
-
enum class E ... extends <parents> ...
46
+
case C_1, ..., C_n
45
47
46
-
expands to a `sealed``abstract` class that extends the `scala.Enum` trait:
48
+
expands to
47
49
48
-
sealed abstract class E ... extends <parents> with scala.Enum ...
50
+
case C_1; ...; case C_n
49
51
50
-
3. If `E` is an enum class without type parameters, then a case in its companion object without an extends clause
52
+
Any modifiers or annotations on the original case extend to all expanded
53
+
cases.
51
54
52
-
case C <params> <body>
55
+
3. A simple case
53
56
54
-
expands to
57
+
case C
55
58
56
-
case C <params> <body> extends E
59
+
of an enum `E` that does not take type parameters expands to
57
60
58
-
4. If `E` is an enum class with type parameters `Ts`, then a case in its
59
-
companion object without an extends clause
61
+
val C = $new(n, "C")
60
62
61
-
case C <params> <body>
63
+
Here, `$new` is a private method that creates an instance of of `E` (see
64
+
below).
62
65
63
-
expands according to two alternatives, depending whether `C` has type
64
-
parameters or not. If `C` has type parameters, they must have the same
65
-
names and appear in the same order as the enum type parameters `Ts`
66
-
(variances may be different, however). In this case
0 commit comments