The Liscio Approach to Variants in Swift
In two recent posts — see how we keep calm and carry on? We’re back to tech topics — I wrote about implementing variants in Swift 2.0.
(See Swift question: Enum vs. Struct for Variants and, before that one, Swift Protocols Question.)
In both cases I was definitely thinking like an Objective-C programmer — I was thinking about how to wrap native types in a variant type.
One approach was to use an enum with associated types, which is much like using tagged unions in C. Another approach was to create a different struct for each under-the-hood value type and have them all conform to a Value protocol.
Chris Liscio — Capo author (Capo is genius, FYI) — suggested another approach: Don’t wrap. Don’t box. Just use the native types directly.
That is, instead of creating something like this…
protocol Value {
func valueBySmashingOtherValue(value: Value) -> Value
}
BoolValue : Value {
let value: Bool
func valueBySmashingOtherValue(value: Value) -> Value {
// do something and return a Value
}
}
IntValue : Value {
let value: Int
func valueBySmashingOtherValue(value: Value) -> Value {
// do something and return a Value
}
}
etc.
…do this instead:
protocol Value {
func valueBySmashingOtherValue(value: Value) -> Value
}
extension Bool : Value {
func valueBySmashingOtherValue(value: Value) -> Value {
// do something and return a Value
}
}
extension Int : Value {
func valueBySmashingOtherValue(value: Value) -> Value {
// do something and return a Value
}
}
etc.
That is, extend the native types instead of wrapping them.
In Objective-C you can’t extend BOOL or NSInteger since they’re not object types, but in Swift you can extend Bool and Int and similar types.
At my stage in learning Swift I wouldn’t have thought of this — but Chris did. (Thanks, Chris!)
(The advantages of this approach are, I hope, self-evident.)
PS The code above hasn’t been checked to see if it compiles. (Written directly in MarsEdit.) But you get the idea.
PPS I am frequently tempted to write that Objective-C is my lightsaber. But I don’t think that’s fair. I think it’s more that I’m still learning how Swift can be elegant — and Chris’s approach here counts as an instance of elegance.