<div dir="ltr"><div>Hello David,<br><br></div>Could you elaborate on this more? Seeing the possibilities of FSM&#39;s in Swift using its powerful enum and case pattern matching was one of the moments in which Swift started increasing its allure factor ;).<br><div><div><br>



















<p class="MsoNormal"><span style="font-size:11pt">Part 1 (background and theory):
<a href="http://www.figure.ink/blog/2015/1/31/swift-state-machines-part-1">http://www.figure.ink/blog/2015/1/31/swift-state-machines-part-1</a></span></p>

<p class="MsoNormal"><span style="font-size:11pt">Part 2 (start of the
implementation): <a href="http://www.figure.ink/blog/2015/2/1/swift-state-machines-part-2">http://www.figure.ink/blog/2015/2/1/swift-state-machines-part-2</a></span></p>

<p class="MsoNormal"><span style="font-size:11pt">Part 3: <a href="http://www.figure.ink/blog/2015/2/8/swift-state-machines-part-3-follow-up">http://www.figure.ink/blog/2015/2/8/swift-state-machines-part-3-follow-up</a></span></p>

<p class="MsoNormal"><span style="font-size:11pt">Part 4: <a href="http://www.figure.ink/blog/2015/2/9/swift-state-machines-part-4-redirect">http://www.figure.ink/blog/2015/2/9/swift-state-machines-part-4-redirect</a></span></p>

<p class="MsoNormal"><span style="font-size:11pt"> </span></p>

<p class="MsoNormal"><span style="font-size:11pt">Final gist: <a href="https://gist.github.com/jemmons/f30f1de292751da0f1b7">https://gist.github.com/jemmons/f30f1de292751da0f1b7</a></span></p>





<br><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Jun 1, 2016 at 3:48 PM, David Waite via swift-evolution <span dir="ltr">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">One thing I did often in Java (and miss in Swift) is using their enums to build state machines or implement command patterns for common commands.<br>
<br>
Java enums are a sealed set of subclasses of the enum base type with (hopefully) immutable, singleton instances. So you can do fun things like:<br>
- Define the base class constructor to be called to instantiate the subclasses, and declare the cases with the constructor arguments<br>
- Declare a method on the base type and refine it on 1-2 particular cases<br>
- Declare the enum implements an interface, and implement that interface separately for each case.<br>
- Define data accessors specific to the type (such as the planets example above)<br>
<br>
I like the SuitInfo approach below - with extensions, I think I can get close to what I have done in the past with Java. Maybe one day there is syntax to do this in the language directly<br>
<br>
-DW<br>
<br>
&gt; On May 31, 2016, at 11:44 AM, Vladimir.S via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt; wrote:<br>
&gt;<br>
&gt; I&#39;m not sure about my opinion on this proposal, but I believe you should add this as alternatives of how we can have the similar features today without injecting stored properties into enums  :<br>
&gt;<br>
&gt; enum Suit {<br>
&gt;    case spades<br>
&gt;    case hearts<br>
&gt;    case diamonds<br>
&gt;    case clubs<br>
&gt;<br>
&gt;    struct SuitInfo {<br>
&gt;        let simpleDescription: String<br>
&gt;        let color: UIColor<br>
&gt;        let symbol: String<br>
&gt;        let bezierPath: UIBezierPath<br>
&gt;    }<br>
&gt;<br>
&gt;    var info : SuitInfo {<br>
&gt;        switch self {<br>
&gt;        case .spades:<br>
&gt;            let path = UIBezierPath()<br>
&gt;            // omitted lines ...<br>
&gt;<br>
&gt;            return SuitInfo(<br>
&gt;                simpleDescription: &quot;spades&quot;,<br>
&gt;                color: .blackColor(),<br>
&gt;                symbol: &quot;♠&quot;,<br>
&gt;                bezierPath: path)<br>
&gt;<br>
&gt;        case .hearts:<br>
&gt;            let path = UIBezierPath()<br>
&gt;            // omitted lines ...<br>
&gt;<br>
&gt;            return SuitInfo(<br>
&gt;                simpleDescription: &quot;hearts&quot;,<br>
&gt;                color: .redColor(),<br>
&gt;                symbol: &quot;♥&quot;,<br>
&gt;                bezierPath: path)<br>
&gt;<br>
&gt;        case .diamonds:<br>
&gt;            let path = UIBezierPath()<br>
&gt;            // omitted lines ...<br>
&gt;<br>
&gt;            return SuitInfo(<br>
&gt;                simpleDescription: &quot;diamonds&quot;,<br>
&gt;                color: .redColor(),<br>
&gt;                symbol: &quot;♦&quot;,<br>
&gt;                bezierPath: path)<br>
&gt;<br>
&gt;        case .clubs:<br>
&gt;            let path = UIBezierPath()<br>
&gt;            // omitted lines ...<br>
&gt;<br>
&gt;            return SuitInfo(<br>
&gt;                simpleDescription: &quot;clubs&quot;,<br>
&gt;                color: .blackColor(),<br>
&gt;                symbol: &quot;♣&quot;,<br>
&gt;                bezierPath: path)<br>
&gt;<br>
&gt;        }<br>
&gt;    }<br>
&gt; }<br>
&gt;<br>
&gt; and this:<br>
&gt;<br>
&gt; enum Suit  {<br>
&gt;    case spades<br>
&gt;    case hearts<br>
&gt;    case diamonds<br>
&gt;    case clubs<br>
&gt;<br>
&gt;    struct SuitInfo  {<br>
&gt;        let simpleDescription: String<br>
&gt;        let color: UIColor<br>
&gt;        let symbol: String<br>
&gt;        let bezierPath: UIBezierPath<br>
&gt;    }<br>
&gt;<br>
&gt;    static let spadesInfo : SuitInfo = {<br>
&gt;        let path = UIBezierPath()<br>
&gt;        // omitted lines ...<br>
&gt;<br>
&gt;        return SuitInfo(<br>
&gt;            simpleDescription: &quot;spades&quot;,<br>
&gt;            color: .blackColor(),<br>
&gt;            symbol: &quot;♠&quot;,<br>
&gt;            bezierPath: path)<br>
&gt;    }()<br>
&gt;<br>
&gt;    static let heartsInfo : SuitInfo = {<br>
&gt;        let path = UIBezierPath()<br>
&gt;        // omitted lines ...<br>
&gt;<br>
&gt;        return SuitInfo(<br>
&gt;            simpleDescription: &quot;hearts&quot;,<br>
&gt;            color: .redColor(),<br>
&gt;            symbol: &quot;♥&quot;,<br>
&gt;            bezierPath: path)<br>
&gt;    }()<br>
&gt;<br>
&gt;    static let diamondsInfo : SuitInfo = {<br>
&gt;        let path = UIBezierPath()<br>
&gt;        // omitted lines ...<br>
&gt;<br>
&gt;        return SuitInfo(<br>
&gt;            simpleDescription: &quot;diamonds&quot;,<br>
&gt;            color: .redColor(),<br>
&gt;            symbol: &quot;♦&quot;,<br>
&gt;            bezierPath: path)<br>
&gt;    }()<br>
&gt;<br>
&gt;    static let clubsInfo : SuitInfo = {<br>
&gt;        let path = UIBezierPath()<br>
&gt;        // omitted lines ...<br>
&gt;<br>
&gt;        return SuitInfo(<br>
&gt;            simpleDescription: &quot;clubs&quot;,<br>
&gt;            color: .blackColor(),<br>
&gt;            symbol: &quot;♣&quot;,<br>
&gt;            bezierPath: path)<br>
&gt;    }()<br>
&gt;<br>
&gt;<br>
&gt;    var info : SuitInfo {<br>
&gt;        switch self {<br>
&gt;            case .spades: return Suit.spadesInfo<br>
&gt;            case .hearts: return Suit.heartsInfo<br>
&gt;            case .diamonds: return Suit.diamondsInfo<br>
&gt;            case .clubs: return Suit.clubsInfo<br>
&gt;        }<br>
&gt;    }<br>
&gt; }<br>
&gt;<br>
&gt;<br>
&gt; On <a href="tel:31.05.2016%2017" value="+393105201617">31.05.2016 17</a>:17, Jānis Kiršteins via swift-evolution wrote:<br>
&gt;&gt; I wrote a proposal draft:<br>
&gt;&gt;<br>
&gt;&gt; # Enum case stored properties<br>
&gt;&gt;<br>
&gt;&gt; * Proposal: TBD<br>
&gt;&gt; * Author: [Janis Kirsteins](<a href="https://github.com/kirsteins" rel="noreferrer" target="_blank">https://github.com/kirsteins</a>)<br>
&gt;&gt; * Status: TBD<br>
&gt;&gt; * Review manager: TBD<br>
&gt;&gt;<br>
&gt;&gt; ## Introduction<br>
&gt;&gt;<br>
&gt;&gt; This proposal allows each enum case to have stored properties.<br>
&gt;&gt;<br>
&gt;&gt; ## Motivation<br>
&gt;&gt;<br>
&gt;&gt; Enums cases can have a lot of constant (or variable) static values<br>
&gt;&gt; associated with it. For example, planets can have mass, radius, age,<br>
&gt;&gt; closest star etc. Currently there is no way to set or get those values<br>
&gt;&gt; easily.<br>
&gt;&gt;<br>
&gt;&gt; Example below shows that is hard to read and manage static associated<br>
&gt;&gt; values with each case. It is hard to add or remove case as it would<br>
&gt;&gt; require to add or remove code in four different places in file. Also<br>
&gt;&gt; static associated value like `UIBezierPath` is recreated each time the<br>
&gt;&gt; property is computed while it&#39;s constant.<br>
&gt;&gt;<br>
&gt;&gt; ```swift<br>
&gt;&gt; enum Suit {<br>
&gt;&gt;    case spades<br>
&gt;&gt;    case hearts<br>
&gt;&gt;    case diamonds<br>
&gt;&gt;    case clubs<br>
&gt;&gt;<br>
&gt;&gt;    var simpleDescription: String {<br>
&gt;&gt;        switch self {<br>
&gt;&gt;        case .spades:<br>
&gt;&gt;            return &quot;spades&quot;<br>
&gt;&gt;        case .hearts:<br>
&gt;&gt;            return &quot;hearts&quot;<br>
&gt;&gt;        case .diamonds:<br>
&gt;&gt;            return &quot;diamonds&quot;<br>
&gt;&gt;        case .clubs:<br>
&gt;&gt;            return &quot;clubs&quot;<br>
&gt;&gt;        }<br>
&gt;&gt;    }<br>
&gt;&gt;<br>
&gt;&gt;    var color: UIColor {<br>
&gt;&gt;        switch self {<br>
&gt;&gt;        case .spades:<br>
&gt;&gt;            return .blackColor()<br>
&gt;&gt;        case .hearts:<br>
&gt;&gt;            return .redColor()<br>
&gt;&gt;        case .diamonds:<br>
&gt;&gt;            return .redColor()<br>
&gt;&gt;        case .clubs:<br>
&gt;&gt;            return .blackColor()<br>
&gt;&gt;        }<br>
&gt;&gt;    }<br>
&gt;&gt;<br>
&gt;&gt;    var symbol: String {<br>
&gt;&gt;        switch self {<br>
&gt;&gt;        case .spades:<br>
&gt;&gt;            return &quot;♠&quot;<br>
&gt;&gt;        case .hearts:<br>
&gt;&gt;            return &quot;♥&quot;<br>
&gt;&gt;        case .diamonds:<br>
&gt;&gt;            return &quot;♦&quot;<br>
&gt;&gt;        case .clubs:<br>
&gt;&gt;            return &quot;♣&quot;<br>
&gt;&gt;        }<br>
&gt;&gt;    }<br>
&gt;&gt;<br>
&gt;&gt;    var bezierPath: UIBezierPath {<br>
&gt;&gt;        switch self {<br>
&gt;&gt;        case .spades:<br>
&gt;&gt;            let path = UIBezierPath()<br>
&gt;&gt;            // omitted lines ...<br>
&gt;&gt;            return path<br>
&gt;&gt;        case .hearts:<br>
&gt;&gt;            let path = UIBezierPath()<br>
&gt;&gt;            // omitted lines ...<br>
&gt;&gt;            return path<br>
&gt;&gt;        case .diamonds:<br>
&gt;&gt;            let path = UIBezierPath()<br>
&gt;&gt;            // omitted lines ...<br>
&gt;&gt;            return path<br>
&gt;&gt;        case .clubs:<br>
&gt;&gt;            let path = UIBezierPath()<br>
&gt;&gt;            // omitted lines ...<br>
&gt;&gt;            return path<br>
&gt;&gt;        }<br>
&gt;&gt;    }<br>
&gt;&gt; }<br>
&gt;&gt; ```<br>
&gt;&gt;<br>
&gt;&gt; ## Proposed solution<br>
&gt;&gt;<br>
&gt;&gt; Support stored properties for enum cases just as each case were an<br>
&gt;&gt; instance. Case properties are initialized block after each case<br>
&gt;&gt; declaration.<br>
&gt;&gt;<br>
&gt;&gt; ```swift<br>
&gt;&gt; enum Suit {<br>
&gt;&gt;    let simpleDescription: String<br>
&gt;&gt;    let color: UIColor<br>
&gt;&gt;    let symbol: String<br>
&gt;&gt;    let bezierPath: UIBezierPath<br>
&gt;&gt;<br>
&gt;&gt;    case spades {<br>
&gt;&gt;        simpleDescription = &quot;spades&quot;<br>
&gt;&gt;        color = .blackColor()<br>
&gt;&gt;        symbol = &quot;♠&quot;<br>
&gt;&gt;        let bezierPath = UIBezierPath()<br>
&gt;&gt;        // omitted lines ...<br>
&gt;&gt;        self.bezierPath = bezierPath<br>
&gt;&gt;    }<br>
&gt;&gt;<br>
&gt;&gt;    case hearts {<br>
&gt;&gt;        simpleDescription = &quot;hearts&quot;<br>
&gt;&gt;        color = .redColor()<br>
&gt;&gt;        symbol = &quot;♥&quot;<br>
&gt;&gt;        let bezierPath = UIBezierPath()<br>
&gt;&gt;        // omitted lines ...<br>
&gt;&gt;        self.bezierPath = bezierPath<br>
&gt;&gt;    }<br>
&gt;&gt;<br>
&gt;&gt;    case diamonds {<br>
&gt;&gt;        simpleDescription = &quot;diamonds&quot;<br>
&gt;&gt;        color = .redColor()<br>
&gt;&gt;        symbol = &quot;♦&quot;<br>
&gt;&gt;        let bezierPath = UIBezierPath()<br>
&gt;&gt;        // omitted lines ...<br>
&gt;&gt;        self.bezierPath = bezierPath<br>
&gt;&gt;    }<br>
&gt;&gt;<br>
&gt;&gt;    case clubs {<br>
&gt;&gt;        simpleDescription = &quot;clubs&quot;<br>
&gt;&gt;        color = .blackColor()<br>
&gt;&gt;        symbol = &quot;♣&quot;<br>
&gt;&gt;        let bezierPath = UIBezierPath()<br>
&gt;&gt;        // omitted lines ...<br>
&gt;&gt;        self.bezierPath = bezierPath<br>
&gt;&gt;    }<br>
&gt;&gt; }<br>
&gt;&gt;<br>
&gt;&gt; let symbol = Suit.spades.symbol // &quot;♠&quot;<br>
&gt;&gt; ```<br>
&gt;&gt;<br>
&gt;&gt; The proposed solution improves:<br>
&gt;&gt; - Readability as cases are closer with their related data;<br>
&gt;&gt; - Improves code maintainability as a case can be removed or added in one place;<br>
&gt;&gt; - Improved performance as there is no need to recreate static values;<br>
&gt;&gt; - ~30% less lines of code in given example.<br>
&gt;&gt;<br>
&gt;&gt; ## Detailed design<br>
&gt;&gt;<br>
&gt;&gt; #### Stored properties<br>
&gt;&gt;<br>
&gt;&gt; Enum stored properties are supported the same way they are supported<br>
&gt;&gt; for structs can classes. Unlike enum associated values, stored<br>
&gt;&gt; properties are static to case and are shared for the same case.<br>
&gt;&gt;<br>
&gt;&gt; Properties are accessed:<br>
&gt;&gt; ```swift<br>
&gt;&gt; let simpleDescription = Suit.spades.simpleDescription<br>
&gt;&gt; ```<br>
&gt;&gt;<br>
&gt;&gt; Mutable properties can be set:<br>
&gt;&gt; ```swift<br>
&gt;&gt; Suit.spades.simpleDescription = &quot;new simple description&quot;<br>
&gt;&gt; ```<br>
&gt;&gt;<br>
&gt;&gt; #### Initialization<br>
&gt;&gt;<br>
&gt;&gt; If enum has uninitialized stored property it must be initialized in a<br>
&gt;&gt; block after each case declaration. The block work the same way as<br>
&gt;&gt; struct initialization. At the end of initialization block all<br>
&gt;&gt; properties must be initialized.<br>
&gt;&gt;<br>
&gt;&gt; ```swift<br>
&gt;&gt; enum Suit {<br>
&gt;&gt;    var simpleDescription: String<br>
&gt;&gt;<br>
&gt;&gt;    case spades {<br>
&gt;&gt;        simpleDescription = &quot;spades&quot;<br>
&gt;&gt;    }<br>
&gt;&gt; }<br>
&gt;&gt; ```<br>
&gt;&gt;<br>
&gt;&gt; Initialization block can be combine with use of `rawValue`:<br>
&gt;&gt;<br>
&gt;&gt; ```swift<br>
&gt;&gt; enum Suit: Int {<br>
&gt;&gt;    var simpleDescription: String<br>
&gt;&gt;<br>
&gt;&gt;    case spades = 1 {<br>
&gt;&gt;        simpleDescription = &quot;spades&quot;<br>
&gt;&gt;    }<br>
&gt;&gt; }<br>
&gt;&gt; ```<br>
&gt;&gt; or associated values of the case:<br>
&gt;&gt;<br>
&gt;&gt; ```swift<br>
&gt;&gt; enum Suit {<br>
&gt;&gt;    var simpleDescription: String<br>
&gt;&gt;<br>
&gt;&gt;    case spades(Int) {<br>
&gt;&gt;        simpleDescription = &quot;spades&quot;<br>
&gt;&gt;    }<br>
&gt;&gt; }<br>
&gt;&gt; ```<br>
&gt;&gt;<br>
&gt;&gt; ## Impact on existing code<br>
&gt;&gt;<br>
&gt;&gt; Stored properties for enums are not currently not supported, so there<br>
&gt;&gt; is no impact on existing code.<br>
&gt;&gt;<br>
&gt;&gt; ## Alternatives considered<br>
&gt;&gt;<br>
&gt;&gt; - Use labeled tuple as `rawValue` of the enum case. This approach is<br>
&gt;&gt; not compatible as it conflicts with intention of `rawValue` of Swift<br>
&gt;&gt; enum;<br>
&gt;&gt; - Use per case initializer like [Java<br>
&gt;&gt; Enum](<a href="https://docs.oracle.com/javase/tutorial/java/javaOO/enum.html" rel="noreferrer" target="_blank">https://docs.oracle.com/javase/tutorial/java/javaOO/enum.html</a>).<br>
&gt;&gt; Swift enum uses custom initializer syntax to setup instances, not<br>
&gt;&gt; cases. So this approach is not suitable for Swift.<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt; On Sun, May 29, 2016 at 3:42 PM, Leonardo Pessoa &lt;<a href="mailto:me@lmpessoa.com">me@lmpessoa.com</a>&gt; wrote:<br>
&gt;&gt;&gt; I think that&#39;s the case with enums. You&#39;re changing their current behaviour of only having stored values to one in which it&#39;s computed (even if only once and then stored). Enums are IMO something that have a static value you know beforehand and can count on. That&#39;s why I&#39;m not fond of the accessor proposal. Otherwise I think we&#39;re transforming enums into a closed set of struct instances and one could do that already by using a private init.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; On 29 May 2016, at 3:38 am, Jānis Kiršteins via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt; wrote:<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; I agree with the argument about use of &quot;where&quot;, not replacing the raw<br>
&gt;&gt;&gt;&gt; value and having some kind of initialization block. But I cannot see<br>
&gt;&gt;&gt;&gt; why &quot;accessors&quot; concept is any better than stored properties to solve<br>
&gt;&gt;&gt;&gt; the particular problem. The &quot;accessors&quot; concept has much wider scope<br>
&gt;&gt;&gt;&gt; than enums and is a separate proposal.<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; On Sat, May 28, 2016 at 11:39 PM, Brent Royal-Gordon<br>
&gt;&gt;&gt;&gt; &lt;<a href="mailto:brent@architechies.com">brent@architechies.com</a>&gt; wrote:<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt; - Abusing rawValue is just that: an abuse.<br>
&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt; My original proposal does not replace rawValue and is compatible with it.<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt; `rawValue` has a different purpose from how you&#39;re using it. It&#39;s supposed to allow you to convert your type to some other *equivalent* type, like an equivalent integer or string. Moreover, it&#39;s supposed to allow you to *reconstruct* the instance from the raw value—remember, `RawRepresentable` has an `init(rawValue:)` requirement.<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt; It is *not* supposed to be an ancillary bag of information on the side. You&#39;re cramming a square peg into a round hole here.<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt; (Also, if you use `rawValue` for an ancillary bag of information, that means you *can&#39;t* use it on the same type for its intended purpose. For instance, you would not be able to assign numbers to your Planet enum&#39;s cases to help you serialize them or bridge them to Objective-C. That&#39;s not good.)<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt; - Using `where` just doesn&#39;t match the use of `where` elsewhere in the language; everywhere else, it&#39;s some kind of condition.<br>
&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt; It is also used in generic type constraints. Plus it reads like human<br>
&gt;&gt;&gt;&gt;&gt;&gt; language: `case mercury where (mass: 3.303e+23, radius: 2.4397e6)`<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt; But a generic constraint is also a type of condition: it specifies types which are permitted and divides them from types that are not.<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt; This is *not* a condition. It&#39;s not anything like a condition. It&#39;s simply not consistent with anything else in the language.<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt; - Dictionaries are the most straightforward way to handle this with the current language, but their lack of exhaustiveness checking is a problem.<br>
&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt; Dictionaries can be used as workaround, but they cannot (lack of<br>
&gt;&gt;&gt;&gt;&gt;&gt; exhaustiveness) solve the problem.<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt; I agree that they&#39;re a halfway solution.<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt; If `ValuesEnumerable` were to be accepted (and to have a generic requirement for its `allValues` property), you could write a Dictionary-like type which ensured at initialization time that it was exhaustive. That&#39;s not as good as compile time, but it&#39;s not bad—sort of a three-quarters solution.<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;       struct ExhaustiveDictionary&lt;Key: Hashable, Value where Key: ValuesEnumerable&gt;: Collection, DictionaryLiteralConvertible {<br>
&gt;&gt;&gt;&gt;&gt;               private var dictionary: [Key: Value]<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;               init(dictionaryLiteral elements: (Key, Value)...) {<br>
&gt;&gt;&gt;&gt;&gt;                       dictionary = [:]<br>
&gt;&gt;&gt;&gt;&gt;                       for (k, v) in elements {<br>
&gt;&gt;&gt;&gt;&gt;                               dictionary[k] = v<br>
&gt;&gt;&gt;&gt;&gt;                       }<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;                       if dictionary.count != Key.allValues.count {<br>
&gt;&gt;&gt;&gt;&gt;                               let missingKeys = Key.allValues.filter { dictionary[$0] == nil }<br>
&gt;&gt;&gt;&gt;&gt;                               preconditionFailure(&quot;ExhaustiveDictionary is missing elements from \(Key.self): \(missingKeys)&quot;)<br>
&gt;&gt;&gt;&gt;&gt;                       }<br>
&gt;&gt;&gt;&gt;&gt;               }<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;               var startIndex: Dictionary.Index {<br>
&gt;&gt;&gt;&gt;&gt;                       return dictionary.startIndex<br>
&gt;&gt;&gt;&gt;&gt;               }<br>
&gt;&gt;&gt;&gt;&gt;               var endIndex: Dictionary.Index {<br>
&gt;&gt;&gt;&gt;&gt;                       return dictionary.endIndex<br>
&gt;&gt;&gt;&gt;&gt;               }<br>
&gt;&gt;&gt;&gt;&gt;               subscript(index: Dictionary.Index) -&gt; (Key, Value) {<br>
&gt;&gt;&gt;&gt;&gt;                       return dictionary[index]<br>
&gt;&gt;&gt;&gt;&gt;               }<br>
&gt;&gt;&gt;&gt;&gt;               func index(after i: Dictionary.Index) -&gt; Dictionary.Index {<br>
&gt;&gt;&gt;&gt;&gt;                       return dictionary.index(after: i)<br>
&gt;&gt;&gt;&gt;&gt;               }<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;               subscript(key: Key) -&gt; Value {<br>
&gt;&gt;&gt;&gt;&gt;                       get { return dictionary[key]! }<br>
&gt;&gt;&gt;&gt;&gt;                       set { dictionary[key] = newValue }<br>
&gt;&gt;&gt;&gt;&gt;               }<br>
&gt;&gt;&gt;&gt;&gt;       }<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt; What I would do is borrow the &quot;accessors&quot; concept from the property behaviors proposal and extend it so that it supported both functions and variables.<br>
&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt; Wouldn&#39;t accessor just be a redundant keyword here? Currently enums do<br>
&gt;&gt;&gt;&gt;&gt;&gt; not support stored properties, so I guess there is no extra need to<br>
&gt;&gt;&gt;&gt;&gt;&gt; mark properties with any special keyword.<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt; The keyword is mainly to indicate the unusual syntax at the definition site, where you only have to specify the name of the accessor you&#39;re defining, not a `func` or `var` keyword, a return type, or even parameter names. (Like `willSet`, there&#39;s a default parameter name you can use.) Secondarily, though, I think it&#39;s helpful to indicate very explicitly that this is not an ordinary method or property definition, even if the compiler could perhaps sort things out without it. `accessor` is something a user can Google if they&#39;ve never seen it before.<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt; Property accessors might work for enums with associated values, but<br>
&gt;&gt;&gt;&gt;&gt;&gt; not so well without them.<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt; The two have nothing to do with each other. I showed your planets example, which has no associated values but uses accessors just fine.<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt; --<br>
&gt;&gt;&gt;&gt;&gt; Brent Royal-Gordon<br>
&gt;&gt;&gt;&gt;&gt; Architechies<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; _______________________________________________<br>
&gt;&gt;&gt;&gt; swift-evolution mailing list<br>
&gt;&gt;&gt;&gt; <a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
&gt;&gt;&gt;&gt; <a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
&gt;&gt; _______________________________________________<br>
&gt;&gt; swift-evolution mailing list<br>
&gt;&gt; <a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
&gt;&gt; <a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
&gt;&gt;<br>
&gt; _______________________________________________<br>
&gt; swift-evolution mailing list<br>
&gt; <a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
&gt; <a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
<br>
<br>_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
<br></blockquote></div><br></div></div></div></div>