> On Mar 14, 2016, at 5:51 PM, Dmitri Gribenko via swift-evolution
> <[email protected]> wrote:
>
> Optional.map returns an Optional.
>
> Array.map returns an Array.
> Set.map returns an Array.
> <any other collection>.map returns an Array.
>
> I can't say that it is not valid to think about an Optional as a tiny
> collection, but as implemented in Swift, .map() does objectively
> behave differently...
That behavior is, at least partially, because protocols don’t currently support
this:
protocol CollectionType {
typealias T
func map<U>(transform: T->U) -> Self<U> // error: Cannot specialize
non-generic type 'Self'
}
I *think* I remember reading on here somewhere that the intent is to change map
and flatMap to return “Self<U>" pretty much as soon as the language supports
it. Someone from Apple would have to confirm that, though… my memory is quite
hazy on the matter.
More to the point, in terms of what you could actual do with a variable,
there’s no real difference between:
var foo: [Int] = []
and
var foo: Int? = nil
In both cases you have to check foo's “count” so to speak, before you can
safely access its element(s), otherwise the most you can do is pass it along to
some other code. If the language had the features to support it, Optional could
literally be defined like this:
typealias Optional<T> = Array<T where self.count <= 1>
While the syntax of how we’d interact with Optionals might change, functionally
speaking, I can’t think of any difference at all. Both provide storage for a
variable # of elements (only slightly variable in Optional’s case, but variable
none the less), both throw equally fatal errors if you try to access elements
that don’t exist, and provide quick access to those that do exist. Furthermore,
within the limitation of how many “elements” an Optional can store, it’s
trivial to convert between the two types:
extension Array {
init(_ x: Element?) {
switch x {
case .None: self = []
case .Some(let value): self = [value]
}
}
}
extension Optional {
init(arrayLiteral elements: [Optional.Wrapped]) {
switch elements.count {
case 0: self = .None
case _: self = .Some(elements[0])
}
}
}
All this suggests, to me anyway, that at least in this regard, they’re the same
“meta type”. What’s the harm in having the API reflect that?
- Dave Sweeris
P.S. Should we be having this conversation in a different thread? I’m *really*
bad about going down every rabbit hole I can find, and I don’t want to upset
the mailing list by dragging them along with me..._______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution