[swift-evolution] Consolidate Code for Each Case in Enum
Anton Zhilin
antonyzhilin at gmail.com
Wed Jan 11 14:57:16 CST 2017
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.
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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170111/84966020/attachment.html>
More information about the swift-evolution
mailing list