What happens if I need an API that returns a Planet from our solar system? Suppose I am a library maintainer and this API is public for consumers of my library. What data structure do I use to represent that Planet? Our first choice might be something like an enum. This is an example from TSPL:
public enum Planet {
case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune
}
This works… but what happens when we add a new Planet?
public enum Planet {
...
case pluto
}
This is now a breaking change. Evolution proposals like SE-0192 and SE-0260 have shipped solutions to help protect against this from happening. A different approach is suggested here by @curt:
Here is what this idea would look like on our Planet:
public struct Planet {
private var kind: Kind
public static var mercury: Planet { Planet(kind: .mercury) }
public static var venus: Planet { Planet(kind: .venus) }
public static var earth: Planet { Planet(kind: .earth) }
public static var mars: Planet { Planet(kind: .mars) }
public static var jupiter: Planet { Planet(kind: .jupiter) }
public static var saturn: Planet { Planet(kind: .saturn) }
public static var uranus: Planet { Planet(kind: .uranus) }
public static var neptune: Planet { Planet(kind: .neptune) }
private enum Kind {
case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune
}
}
This pattern works and is already being used across the ecosystem. But do we really need all this boilerplate? Could we image a world where we could do this:
@algebraic public struct Planet {
case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune
}
Where a potential algebraic attribute synthesizes that extra boilerplate for us so that our struct functions more similar to an Algebraic data type? While also offering an alternative solution to prevent breaking changes from adding new case values?
I could probably hack something together with macros that can sort of make this work today… but I was also throwing this out there to see if anyone else had thoughts about whether or not this belongs in the language itself.
If we do not choose to ship something like this as part of the language itself… would anyone be interested in helping to update TSPL to explain more about the long-term effects of relying on enum values across API boundaries? I do understand we like to achieve an ideal of progressive disclosure without front-loading too much information… but I also think this topic is important enough that future library maintainers might need to learn more about this sooner rather than later.