An extension ...
fileprivate extension Optional {
///Do an upsert for one item - works on all groups
mutating func upsert<T: MyProtocol>(item: T) where Wrapped == [T] {
}
}
which you can call like this
for i in updates.dogs {
stuff.dogs.upsert(item: i)
}
for i in updates.cats {
stuff.cats.upsert(item: i)
}
... dozens of those ...
... dozens of those ...
for i in updates.chooks {
stuff.chooks.upsert(item: i)
}
dogs
etc is a [Dogs]?
, Dogs
Cats
etc are structs of MyProtocol
It would be nicer to
stuff.dogs.upsertAll(from: updates.dogs)
stuff.cats.upsertAll(from: updates.cats)
Soooo ...
If you
fileprivate extension Optional {
mutating func upsertAll<T: MyProtocol >(from: [T]) where Wrapped == [T] {
..
for i in from {
self!.upsert(item: i)
Result,
Value of type 'Array<T>' has no member 'upsert'
self!
is an array of [Dogs]
ans Dogs
etc are MyProtocol
.
Is there a way?
I'm not sure where the idea of unwrapping self
(self!
) came from. upsert
is an extension on Optional
, so you should not unwrap self
in upsertAll
if you want to call upsert
.
fileprivate extension Optional {
mutating func upsertAll<T: MyProtocol>(from: [T]) where Wrapped == [T] {
for i in from {
self.upsert(item: i)
}
}
}
Also consider taking in any type that is a Sequence<T>
if all you need is the ability to use a for
loop on it.
mutating func upsertAll<S: Sequence<T>, T: MyProtocol>(from: S) where Wrapped == [T] {
for i in from {
self.upsert(item: i)
}
}
Also consider relaxing the restriction on Wrapped
to a more general protocol type (e.g. BidirectionalCollection
), though of course this depends on what you are doing in upsert
.
I am assuming that upsert
will still have some side effect even if self
is nil. If that is not the case, it is rather un-idiomatic to declare upsert
as an Optional
extension. It would be more idiomatic to declare it as an extension of Array
, and the call site would use optional chaining (stuff.dogs?.upsert(item: dog)
) to call it.
fileprivate extension Array where Element: MyProtocol {
mutating func upsert(item: Element) {
}
mutating func upsertAll(from: some Sequence<Element>) {
for i in from {
self.upsert(item: i)
}
}
}
The key difference here (compared to your attempted extension on Array
) is to use the Element
type in the method declarations.