From alternatives section:
I like a variation of the above alternative, IMHO it deserves consideration:
// given this enum:
enum E {
case foo(bar: Int, String)
case qux
}
// let's assume this was autogenerated:
// (see implementation details below)
extension E {
var foo: (bar: Int, String)! { ... }
var qux: E! { ... }
}
// then we can write:
var e = E.foo(bar: 1, "hello")
print(e) // foo(bar: 1, "hello")
print(e.qux) // nil
print(e.foo) // Optional((bar: 1, "hello"))
print(e.foo.bar, e.foo.1) // 1 hello
print(e.foo?.bar, e.foo?.1) // Optional(1) Optional("hello")
print(e.foo != nil) // true
print(e.qux != nil) // false
print(e.foo?.bar != nil) // true
let (bar, baz) = e.foo
print(bar, baz) // 1 hello
print(e.qux) // nil
e.foo.bar = 2 // mutating associated value! 😃 (traps if not foo)
print(e.foo) // Optional((bar: 2, "hello"))
e.foo?.1 = "world" // mutating associated value by index this time
print(e.foo) // Optional((bar: 2, "world"))
Implementation details
// let's assume this is autogenerated:
extension E {
var foo: (bar: Int, String)! {
get {
switch self {
case let .foo(bar: bar, baz): return (bar: bar, baz)
default: return nil
}
}
set {
let val = newValue!
self = .foo(bar: val.bar, val.1)
}
}
var qux: E! {
get {
switch self {
case .qux: return E.qux
default: return nil
}
}
set {
precondition(newValue != nil)
self = .qux
}
}
}
Edited: updated the sample and implementation details