[swift-evolution] Request: Ability to refer to an enum case in abstract (without its associated value)
emaloney at gilt.com
Fri Dec 11 14:55:53 CST 2015
> I don’t think this suggestion would work in practice. It’s the equivalent of trying to construct a struct value with non-optional properties, but without providing any init parameters, it would result in an invalid value. If your proposal were possible I think it would cause trouble with pattern matching enums too. In a switch statement that expects to bind to associated values, what happens when it receives an enum that should have associated values, but they are not present?
I am definitely not proposing any change in the current behavior of enums, cases, pattern matching, or anything like that.
I'm proposing adding a way of representing something that currently can't be represented in Swift.
You can match an enum case by ignoring the associated values it contains, but that's matching against a value that has *already been created with associated values*.
There's no way to create a value in Swift that represents the general form of an enum case when that case is declared with associated values. You can only create a value in the specific form, i.e. the form of the case that actually contains the associated values. There's no way to represent the general form.
Bear with my inaccurate analogy here, because it might provide a better explanation of what I'm talking about:
In an enum, when a case has no associated values, you can think of values of that case behaving like a type in that there's only one version of it that can exist: the thing itself. There's no range of values that can be represented by such an enum case; there's just one value.
Now, once you introduce associated values, the concept of an enum case suddenly changes: it no longer represents a single thing, it represents a potential range of things. In other words, realized versions of those case values stop acting like types and start acting like instances of a type.
Anywhere else in Swift where something acts like a value, there's an equivalent metavalue type that can also be represented in a Swift variable.
Why would I want to do this?
It seems to me it's quite common in software development that when you model specific instances of things, you also need a way to represent the general form of those specific things.
In my case, I want to model a set of screens with specific content, I might do that with an enum containing associated values. The case represents the screen, and the associated values represent the content.
However, in addition to representing the specific, I also need to model the general. Instead of modeling screens with specific content, I also need to programmatically model just the screens themselves, without any specific content.
My solution was to allow such enums to opt-in to a protocol that would cause the compiler to generate a parallel enum that contains the same cases, minus the associated values.
This parallel enum would be an entirely different type, and it would not affect the current semantics of the original enum (with the associated values) that it "shadows".
I've run into several use cases for this in about a year of Swift coding, and each time I've come up with a manual work-around (just as others have suggested various ways to work around this) but in each case, I lose the compiler's ability to enforce the conditions that I must now assert at runtime.
More information about the swift-evolution