- Proposal: TBD
- Author(s): Yong hee Lee
- Status: TBD
- Review manager: TBD
This proposal submits a Swift language enhancement that creates anonymous enumerations for simple flag variables. Swift already supports anonymous functions (closures) and a restricted form of anonymous structs with tuples. This proposal introduces an anonymous approach for enumerations, enabling an anonymous variant for each fundamental entity in the language.
The Swift-Evolution discussion of this topic took place in the Anonymous Enums (Updated) thread. This proposal uses lowerCamelCase enumeration cases in compliance with current API Guideline Working Group guidance.
An anonymous enumeration is a flag variable type. It creates semantically rich Swift code without the overhead required to introduce extra types. This feature does not replace normal enumerations. An enumeration that's used in more than once place, has associated or raw values, or provides semantics beyond use as a flag is not a suitable candidate for this proposal.
Instead, anonymous enumerations capture simple flag states using a parsimonious syntax. They might replace Boolean flags so API consumers needn't translate the meaning of the flag to or from truth values or they might introduce a limited collection of possible values, such as colors or temperature levels.
Anonymous enumerations push semantics to the context of a call, letting that call use meaningful tokens. This produces streamlined, use-specific syntax both at the call site and in the method and function declarations where they are defined.
Anonymous enumerations:
- Streamline coding, eliminating standalone types that are used only once.
- Enable you to see all enumeration options at a glance.
- Encourage switch-case coding.
As you will see in the detail design, anonymous enumerations are a small difference that introduce a big change in Swift.
The proposed anonymous enumeration syntax combines one-use enumerations into a single group integrated into a method or function's type.
func adjustTemperature(temperature temp: [ low | normal | high ]) throws { ... }
A multi-line declaration might look like this:
func adjustTemperature(
device: DeviceType,
temperature temp: [ low | normal | high ]
) throws
Anonymous enumerations would be practically limited to 255 tokens and probably should not be used for more than two to five items in actual code.
Note: The square bracket syntax used here may need to change due to possibles conflict with collections.
At this time, one-use enumerations must be declared separate from the context that consumes them. Here is an example of a one-use Temperature
enumeration declared in current Swift.
struct MyTempStruct {
// Temperature type declared here
enum Temperature {case low, normal, high}
// Temperature type used here
func adjustTemperature(device: DeviceType, temp: Temperature) throws {
//...
}
}
Incorporating a one-time-use enumeration into a function or method streamlines code and reduces excess declarations. If adopted, the temperature enumeration from the preceding example is subsumed into the declaration, as shown here:
struct MyTempStruct {
func adjustTemperature(
device: DeviceType,
temperature temp: [ low | normal | high ]) throws {
//...
}
}
In the current version of Swift and Xcode, the Quick Help output for
adjustTemperature()
produces the following Declaration
line:
func adjustTemperature(device: DeviceType, temperature temp: Temperature) throws
Under this proposal, Quick Help updates to provide an instant reference for consumers. It incorporates the anonymous enumeration options directly into the calling pattern shown to the API consumer.
func adjustTemperature(device: DeviceType, temperature temp: [ low | medium | high ]) throws
The current version of Swift encourages if-statement consumption of Boolean values. For example:
var switchIsOn : Bool = true
if switchIsOn {
// ...
print("...on...")
// ...
} else { // no further context here other than "else"
// ...
print("...off...")
// ...
}
In contrast, anonymous enumerations lend themselves to switch statements.
switch switchState {
case .on:
// ...
print("...on...")
// ...
case .off:
// ...
print("...off...")
// ...
}
The result is cleaner, easier-to-follow coding. The switch statement provides
better readability, labeling each case for easy visual identification.
Switch statements push back against nested, complex if
-statement coding.
They produce better structured code where each branch is fully labeled
in contrast with unlabeled else
clauses.
Using collection syntax for enumeration flags may be problematic. It is left as an exercise for the mailing list and the Swift team to suggest possible alternatives such as:
func f (switchState: [ on | off ]) { ... } // current
func f (switchState: <on | off >) { ... } // angles
func f (switchState: (on, off)) { ... } // parens, commas
func f (switchState: ( on | off )) { ... } // parens, pipes
func f (switchState: {case on, off}) { ... } // comma-delim cases
func f (switchState: enum(on, off)) { ... } // enum syntax, commas
func f (switchState: enum( on | off )) { ... } // enum syntax, pipes
// ...etc...
@erica agreed, that type is missing. I mean to suggest that the absence of that type presents a major hurdle if anonymous enumerations were available to be used in an interface.
Consumer of an interface are constrained to passing in-line literal arguments for every permutation of anonymous enumeration values. Imagine if I gave you
func adjustEnvironment(temperature temp: [ low | normal | high ], humidity: [ low | normal | high ], pressure: [ low | normal | high ])
and you tried to map some set of user input into calls to that method. Anonymous enumerations would make it easier to write difficult to use interfaces.Providers of an interface using anonymous enumerations receive value typed arguments which are effectively
@noescape
'ed. These argument can never be directly passed on no matter how reasonable it would be to do so. Anonymous enumerations would make it easy to write interfaces which constrain their implementation.I don't believe the benefit of quick enumeration declarations would be worth the cost anonymous enumerations would impose on a code base. Only the initial author would be well served by this feature at great cost to anyone who attempts to use the resulting interface in the future.