Jens
1
Note that I'm only using Collection and Optional here to provide a simple (albeit contrived) example of a more general question.
(The more general question perhaps being something like: "Why can't an associated type (eg Element) be constrained to being any particular concretization of some generic type (eg Optional<T>)? And how can this limitation be worked around in this specific example?")
Anyway, It's probably better to just focus on the question at the end of this little program:
extension Collection where Element == Optional<Float> {
var someElementCount : Int {
return self.reduce(0) { (partialResult, element) in
switch element {
case .none: return partialResult
case .some: return partialResult + 1
}
}
}
var noneElementCount : Int { return count - someElementCount }
}
let a: [Float?] = [1.2, 3.4, nil]
print(a.count) // 3
print(a.someElementCount) // 2
print(a.noneElementCount) // 1
// Now, I would of course like to have this functionality for any `Optional<T>`
// (and not just for `Optional<Float>`). So eg the following should also work:
let b: [String?] = ["abc", nil, "ghi"]
print(b.count) // 3
// print(b.someElementCount) // Should print 2
// print(b.noneElementCount) // Should print 1
// How do I accomplish this? (Without type erasing to [Any?])
It's not pretty, and forgive the naming, etc, but
protocol OptionalConvertible {
associatedtype Element
var asOptional: Optional<Element> { get }
}
extension Optional: OptionalConvertible {
var asOptional: Optional<Wrapped> { return self }
}
extension Collection where Element: OptionalConvertible {
var someElementCount : Int {
return self.reduce(0) { (partialResult, element) in
switch element.asOptional {
case .none: return partialResult
case .some: return partialResult + 1
}
}
}
var noneElementCount : Int { return Int(count) - someElementCount }
}
let a: [Float?] = [1.2, 3.4, nil]
print(a.count) // 3
print(a.someElementCount) // 2
print(a.noneElementCount) // 1
let b: [String?] = ["abc", nil, "ghi"]
print(b.count) // 3
print(b.someElementCount) // Should print 2
print(b.noneElementCount) // Should print 1
1 Like
The feature you're asking for is simply not implemented yet.
1 Like
Jens
4
Thanks! I could only come up with workarounds similar to the one @jawbroken gave, so I figured I was missing something obvious or that there was something missing in the language.