tim_s
(Tim)
1
Is there a way to define an extension on an Array where the Element is a type with a generic? I know it's possible to declare an extension if I make the generic a concrete type, but what if I want to remain generic here?
E.g.
extension Array where Element == Range<Date> {
func foo() {
// Do something
}
}
Is there a way to specify Bound instead?
7 Likes
Nevin
2
I believe you are asking for what the generics manifesto calls parameterized extensions.
I agree this would be useful, though it is not yet possible in Swift.
9 Likes
tim_s
(Tim)
3
Ah, this is exactly it. In fact, I even tried this proposed syntax when seeing if I could get it work. At least I know there is a name for the proposed behaviour now and I can track it. Thanks Nevin.
nnnnnnnn
(Nate Cook)
4
The workaround for this kind of thing is to make a protocol that can produce the parameterized type that you want, like so:
protocol Rangey {
associatedtype Bound: Comparable
var range: Range<Bound> { get }
}
extension Range: Rangey {
var range: Range<Bound> { return self }
}
extension Array where Element: Rangey, Element.Bound == Date {
func contains(date: Date) -> Bool {
return contains(where: { $0.range.contains(date) })
}
}
6 Likes
tim_s
(Tim)
5
This is the behaviour I am trying to achieve:
class Weak<Value: AnyObject> {
weak var value: Value?
init(_ value: Value) {
self.value = value
}
}
protocol Weakly {
associatedtype Value: AnyObject
var weak: Weak<Value> { get }
}
extension Weak: Weakly {
var weak: Weak<Value> { return self }
}
extension Array where Element: Weakly {
func contains(_ value: Weakly) -> Bool {
return self.flatMap( { $0.weak.value } ).contains(value)
}
}
I am trying to create a generic convenience contains() call on an array that contains Weak boxed types. Tried using your approach but couldn't quite get it how I wanted.
nnnnnnnn
(Nate Cook)
6
I think in the method you want the parameter to be Element.Value:
extension Array where Element: Weakly, Element.Value: Equatable {
func contains(_ value: Element.Value) -> Bool {
return self.contains(where: { $0.weak.value == value })
}
}
This also uses contains in place to save the extra processing, and adds a constraint that the value has to be equatable.
2 Likes
tim_s
(Tim)
7
Ah perfect. Got it working:
extension Array where Element: Weakly, Element.Value: Equatable {
func contains(_ value: Element.Value) -> Bool {
return self.flatMap( { $0.weak.value } ).contains(where: {$0 == value})
}
}
I am flatMapping as I want the convenience of being able to pass in objects not boxed in Weak.
EDIT: Just realised that is not required at all!
Thanks!
4 Likes