Sent from my iPhone
> On Jan 11, 2017, at 14:57, Anton Zhilin via swift-evolution 
> <swift-evolution@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
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to