Reputation: 1500
extension Array {
init?<S: Sequence>(_ sequence: S?) where S.Element == Element {
guard let sequence = sequence else { return nil }
self.init(sequence)
}
}
extension Set {
init?<S: Sequence>(_ sequence: S?) where S.Element == Element {
guard let sequence = sequence else { return nil }
self.init(sequence)
}
}
As you can see the code in both extensions is absolutely identical. So how can I rewrite it without repetitiveness? Something like:
extension Collection where type == Array || type == Set {
init?<S: Sequence>(_ sequence: S?) where S.Element == Element {
guard let sequence = sequence else { return nil }
self.init(sequence)
}
}
Upvotes: 0
Views: 69
Reputation: 273380
The initialiser you want to add to Array
s and Set
s can in fact be added to all Sequences
, because you are not using anything that is unique in Array
or Set
. All that the initialiser depends on is:
Element
associated typeSequence
Sequence
satisfies the first criteria, and there is no common protocol between Array
and Set
that satisfies the second :-(. The one from Array
comes from RangeReplaceableCollection
. The one from Set
comes from SetAlgebra
.
You can create such a protocol yourself though:
protocol SequenceInitialisable : Sequence {
init<S: Sequence>(_ s: S) where S.Element == Element
}
extension Array : SequenceInitialisable {}
extension Set : SequenceInitialisable {}
extension SequenceInitialisable {
init?<S: Sequence>(_ sequence: S?) where S.Element == Element {
guard let sequence = sequence else { return nil }
self.init(sequence)
}
}
Or (as you said) you can just do sequence.map(Array.init)
if you don't mind writing map
and init
.
A tip on writing extensions: Try to find all the things that your extension depends on/needs, and then find the most general type that has all of those things. That is the type you should write the extension on.
Upvotes: 3
Reputation: 5073
You can do something like this:
protocol NilSequenceInitializable {}
extension NilSequenceInitializable where Self: Sequence {
init?<S: Sequence>(_ sequence: S?) where S.Element == Element {
guard let sequence = sequence else { return nil }
self.init(sequence)
}
}
extension Array: NilSequenceInitializable {}
extension Set: NilSequenceInitializable {}
Upvotes: 1