Wow, my thread was revived! From almost a year ago! I'm glad there's some interest in the topic.
Much of this discussion is focusing on Optional. It's good that we have map (though it's neither discoverable nor readable), but I would like to see enums generally be more useable.
Enums with associated types are a pretty neat feature of Swift. However, they require more lines and more unique syntax than alternatives - the primary alternative being a closed class hierarchy. Enums save in declaration verbosity at the expense of usage verbosity - and that's the exact opposite of what a developer wants! The only advantages I see are 1) compile time checking (switch statement warnings/errors) 2) specific performance consideration (stack allocation).
If a developer ends up making enough extension methods on the enum to make it reasonably useable, it may as well have been a class to start with, as the class and class hierarchy can at least be extended as the application grows.
Working under the assumption that enums are a type that should be favored when possible, the syntax should not be punitive. if case is pretty unintuitive, IMO, which leaves us with switch and manually written map-like extensions.
For illustration, let's say we have a DatabaseValue type and want to extract a string if the stored type is a string:
enum DatabaseValue {
case string(_: String)
case integer(_: Int)
// ...
}
func printStringValue(_ dbValue: DatabaseValue) {
let result: String
if case let .string(strValue) = dbValue {
result = strValue
} else {
result = ""
}
print("the string is \(result)")
}
But if DatabaseValue were a root class:
class DatabaseValue {
}
class StringDatabaseValue: DatabaseValue {
public let stringValue: String
//...
}
func printStringValue(_ dbValue: DatabaseValue) {
let result = (dbValue as? StringDatabaseValue)?.stringValue ?? ""
print("the string is \(result)")
}
The latter usage is denser, but more readable: the reader knows that result is being calculated here and can skim past it. It is only when the reader wants to know how result is being derived that the readability becomes debatable. Since extracting a value from an enum is such an insignificant task when compared to other code, it doesn't deserve vertical space.
Another alternative is Any, if it applies:
func printStringValue(_ dbValue: Any) {
let result = (dbValue as? String) ?? ""
print("the string is \(result)")
}
Why would we want to encourage Any over enum types?
The current syntax for enum usage seems to hold the opinion "if you are using an enum, you will want to handle all of its cases everywhere, so a switch statement is just fine". In my experience, this is an unrealistic expectation.
To bring things back around, it is my opinion that unwrapping and using a value from an enum, whether it's Optional or another, should always be possible within a single statement. Once you need block statements or helper extensions to extract a value, the wrapper type's usage semantics are just adding rote signal noise.