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

David Sweeris davesweeris at mac.com
Wed Jan 11 15:51:38 CST 2017




Sent from my iPhone
> On Jan 11, 2017, at 14:57, Anton Zhilin via swift-evolution <swift-evolution at swift.org> wrote:
> 
> Wouldn’t protocols be a better solution in this case? If little to no logic can be shared between enum cases, why have the enum in the first place?
> 
> Your variant:
> 
> protocol State {
> 
>     mutating func react(to event: Event)
> }
> 
> enum AuthenticationState: State, CustomStringConvertible {
> 
>     case invalid {
>         var description: String { return "Authentication invalid." }
> 
>         mutating func react(to event: Event) {
>             switch event {
> 
>             case let login as UserLoggedIn:
>                 self = .validated(token: login.token)
>             default:
>                 break
>             }
>         }
>     }
> 
>     case expired(_ expiration: Date) {
>         var description: String { return "Authentication expired at \(expiration)." }
> 
>         mutating func react(to event: Event) {
>             switch event {
>             case let refreshed as TokenRefreshed:
> 
>                 self = .validated(token: refreshed.token)
> 
>             default:
>                 break
>             }
>         }
>     }
> 
>     case validated(token: String) {
> 
>         var description: String { return "The authentication token is \(token)." }
> 
>         mutating func react(to event: Event) {
>             switch event {
> 
>             case let expiration as TokenExpired:
>                 print("Expiring token: \(token)")
>                 self = .expired(expiration.date)
>             case _ as TokenRejected:
>                 self = .invalid
>             case _ as UserLoggedOut:
>                 self = .invalid
>             default:
>                 break
>             }
>         }
>     }
> 
> }
> My suggestion:
> 
> public protocol State {
> 
>     mutating func react(to event: Event)
> }
> 
> @closed protocol AuthenticationState : State, CustomStringConvertible { }
> 
> struct InvalidAuthenticationState : AuthenticationState {
>     var description: String { return "Authentication invalid." }
> 
>     mutating func react(to event: Event) {
>         switch event {
> 
>         case let login as UserLoggedIn:
>             self = .validated(token: login.token)
>         default:
>             break
>         }
>     }
> }
> 
> struct ExpiredAuthenticationState : AuthenticationState {
>     var expiration: Date
> 
>     var description: String { return "Authentication expired at \(expiration)." }
> 
>     mutating func react(to event: Event) {
>         switch event {
>         case let refreshed as TokenRefreshed:
> 
>             self = .validated(token: refreshed.token)
> 
>         default:
>             break
>         }
>     }
> }
> 
> struct ValidatedAuthenticationState : AuthenticationState {
>     var token: String
> 
>     var description: String { return "The authentication token is \(token)." }
> 
>     mutating func react(to event: Event) {
>         switch event {
> 
>         case let expiration as TokenExpired:
>             print("Expiring token: \(token)")
>             self = .expired(expiration.date)
>         case _ as TokenRejected:
>             self = .invalid
>         case _ as UserLoggedOut:
>             self = .invalid
>         default:
>             break
>         }
>     }
> }
> If AuthenticationState is not public, then compiler can make an optimization and turn existentials and indirect calls into an enum, essentially.
> We can even split public protocols into open and public, as we did with classes, to allow for expressing this intent more explicitly.
> 
I don't understand the lines in the struct version where you assign something to `self`. What is ".invalid", for example? I thought you'd removed the enum altogether.



> But pattern matching on structs is impossible—we can change that with a separate proposal. For example, we can allow destructuring structs/enums/classes by any combination of their properties:
> 
> struct S {
>     var foo: Int
>     var bar: Double
>     var buz: String { return "42" }
> }
> 
> let s = S(foo: 42, bar: 42.0)
> 
> let S(foo: x, buz: z) = s
I was under the impression that we could switch over anything that had the `~=` operator defined. Is that not the case?

- Dave Sweeris
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170111/f37308c4/attachment.html>


More information about the swift-evolution mailing list