Optional.map(_:) is a great way to perform lots of operations that cannot make use of Optional Chaining syntactic sugar. However, it is identical to Optional.flatMap(_:) except for the limitation that map's closure must return a nonoptional value. Basically, map is a specialized version of flatMap that performs the exact same function, removing the need for it to be specialized.
I propose deprecating Optional.map(_:) in favor of Optional.flatMap(_:). This does not break ABI stability. Source compatibility is not broken either, but the automatic migrator should convert all instances of map to flatMap to avoid deprecation warnings.
The existence of two entirely separate methods for this behavior is confusing and unnecessary. Any code that uses map can already be converted to flatMap with no impact on functionality (but not vice versa).
An alternative to this is to deprecate flatMap and make map behave like flatMap.
One thing I'd like to see along with this is a case study of how map and flatMap are used currently. If there's evidence of misuse in current code, this this might make sense. Otherwise it would probably be too large of a source break at this point.
@AlexanderM Could you please elaborate? I'm not sure exactly what you're referring to.
@saagarjha For example usages, see the linked documentation for those two functions. The proposal is not to remove map, just to deprecate it to unify the two functions. They do exactly the same thing, and map is just a specialized version of flatMap. The specialization is unnecessary because the map does not change any behavior; map simply requires its closure to return a nonoptional value, but then returns an optional even if its closure does run and return.
I'm talking about usage by developers, pulled from say GitHub. If we see people using flatMap where map would have sufficed it provides credibility to your claim that map is unnecessary.
You should be aware that the bar for removal (or deprecation) of an existing API at this stage of Swift Evolution requires empiric demonstration of active harm. A proposal to make such a change will not be successful without such evidence.
I'm pretty sure there is similar code in the wild.
Even worse, due to the way closures are typechecked, the following snippet:
let o = Optional(42)
let result1 = o.map { x in
if x > 0 {
return x
}
return nil
}
print(result1)
let result2 = o.flatMap { x in
if x > 0 {
return x
}
return nil
}
print(result2)
does not compile, producing:
error: unable to infer complex closure return type; add explicit type to disambiguate
let result2 = o.flatMap { x in
^
-> (Int)
map makes sense, but flatMap should likely be renamed to compactMap to match the change on Sequence in Swift 4.1. I'm not sure the typical flatMap has a place on Optional.
I don't think that's right. The Sequence.flatMap that takes an (Element) -> T? closure was renamed to compactMap to disambiguate from the monadic flatMap. Optional.flatMap is exactly this monadic flatMap, so renaming it to compactMap would not make sense.
These functions and their names are well-established over many programming languages, math, and other disciplines, so renaming them to something else in Swift would only cause more confusion and is unlikely.
In math, "map" means "function", so yep! And a map (function) has a domain (argument) and codomain (return value).