[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