This is loosely related to but not meant to 'compete' with the ad hoc enum proposal.
This proposal adds/creates syntax to allow ad hoc creation of enums whose members are strict subsets of explicitly defined enums.
Swift-evolution thread: Discussion thread topic for that proposal
Consider a situation where we have an enum Color
which represents the entire set of colors relevant to your application with many salient methods and operations. We have also declared an enum LCDColorModel
with only three colors, red, blue, green
.
enum Color {
case red, orange, yellow, green, blue, indigo, violet
…
}
enum LCDColor {
case red, green, blue
}
The cases in LCDColor
in our scenario do not require different behavior from their similarly named cases in Color
. We would like, simply stated, to explicitly restrict the cases allowed within a specific portion of our software. There are, currently, a few approaches
1. Duplicate functionality in LCDColor
- Completely manually
- Protocols with 'minimal' manual duplication
2. Avoid duplication by allowing conversion to Color
.
Neither of these solutions make the subset relationship between Color
and LCDColor
clear or strict.
Add syntax to describe a restricted set of cases from an enum.
typealias LCDColor = Color.(red|green|blue)
LCDColor
has all of the type and instance methods of Color
.
- Barring any technical reason, the 'actual' name of the type, in this example, is
Color.(red|green|blue)
This makes the relationship toColor
syntactically clear. If a typealias is not desired,Color.(red|green|blue)
should refer to the same type asLCDColor
- Switching over
Color.(red|green|blue)
should only need to be exhaustive for the three cases.red
,.green
, and.blue
. - Two initializers should be implicitly created
Color
toLCDColor?
- returns nil for all cases not in
LCDColor
- returns nil for all cases not in
LCDColor
toColor
- Obvious and trivial implementation mapping cases from
LCDColor
toColor
- Obvious and trivial implementation mapping cases from
- Casting should be allowed
- from superset to subset only using
as?
oras!
syntax. - from subset to superset using
as
- from superset to subset only using
- Creating subsets of subsets is not allowed but reasonable conversions among subsets should be allowed if technically feasible such that:
- Given subsets of
C
A
andB
, where A is a superset of B, the casting relationship betweenA
andB
should be similar to that betweenC
and either of the other two named subsets.
- Given subsets of
- Return types and types associated with protocol conformance should be contravariant. In this way
Color.(red|green|blue)
is not a full fledged type. It cannot have its own conformance to protocols which varies from its superset. eg:
enum Color : _Incrementable {
case red, orange, yellow, green, blue, indigo, violet
var successor: Color {
switch self {
case .red: return .blue
case .blue: return .green
case .green: return .red
}
}
}
enum
let x: Color.(blue|green) = Color.blue
let color = x.nextColor // type is `Color` without narrowing.
While I am unsure of the entirety of the design, I propose that name mangling be used which, along with the declaration order restriction should mean that all possible subsets have a stable and predictable name which contains all of the information necessary to infer cases. If a mangled name approach is taken, the ordering of cases should be sorted to ensure stability.
- Do nothing. This feature is not strictly necessary but does allow for expressivity not currently available in the language.
- implicitly create properties which convert to superset type.
This is an additive change which should have no breaking change to existing code.
Hi @griotspeak I have this need on some of my project do you feel like re-submit this evolution proposal ?