[swift-evolution] Consolidate Code for Each Case in Enum

Tim Shadel timshadel at gmail.com
Thu Jan 12 02:29:24 CST 2017


I think you may be reacting to the very first draft. `extension` isn't used at all in the newest draft, and no code can exist outside the enum. In fact, there's a fair amount of similarity to your idea in the newest proposal.

https://gist.github.com/timshadel/5a5a8e085a6fd591483a933e603c2562


> On Jan 11, 2017, at 6:43 PM, Jay Abbott via swift-evolution <swift-evolution at swift.org> wrote:
> 
> I like the idea behind this, but I think the proposed syntax abuses extension, which applies to types not individual cases. Putting the code outside the enum also seems wrong, and it’s difficult to see how the compiler would handle it, in particular ensuring exhaustiveness. So I have come up with an alternate syntax using the example from the proposal that I think works a bit better (or at least might inspire someone else to improve it further):
> 
> enum TokenState {
>     case expired(at: Date)
>     case validated(token: String)
> 
>     caseprotocol { // (1)
>         mutating func react(to event: Event)
>         var description: String
>     }
>     caseimpl<.expired(let at)> { // (2)
>         var description: String {
>             return "Expired at \(at)"
>         }
>         mutating func react(to event: Event) {
>             switch event {
>             case _ as TokenRefreshed:
>                 self = .validated(token: event.token)
>             default: break
>             }
>         }
>     }
>     caseimpl<.validated(let token)> { // (3)
>         var description: String {
>             return "Token \(token) has been validated."
>         }
>         mutating func react(to event: Event) {
>             switch event {
>             case _ as TokenRejected:
>                 self = .expired(at: Date())
>             case _ as UserLoggedOut:
>                 self = .expired(at: Date())
>             default: break
>             }
>         }
>     }
>     // (4)
> }
> I find this easier to parse manually, and I think the compiler would too…
> 
> At (1) it is equivalent to defining a normal protocol outside the enum. The enum itself would implicitly conform to this protocol. Calculated properties would be implicitly get-only in the protocol.
> At (2) and (3) this would be equivalent to defining a static object that conforms to a compiler-modified version of the protocol, with static implementations of the getters/functions. Mutating functions would have an inout ref to self and they would all have any associated values sent in as per the let in the caseimpl declaration. The body would come directly from the programmer code.
> At (4) the compiler would generate the enum’s implementation to conform to the protocol, this would switch on self and call the appropriate static functions. As per the original proposal.
> It might be good if you don’t have to repeat all the func signatures in each caseimpl - I considered a different syntax where you defined a casefunc (similar to a typealias) like casefunc ReactTo = mutating func react(to event: Event) then in the caseimpl you could just do ReactTo = { func body here } but it didn’t seem to fit. Hopefully someone else will have some ideas to reduce the repetition.
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170112/725dce9b/attachment.html>


More information about the swift-evolution mailing list