For RangeReplaceableCollection.append(repeating: count:)
, you can replace that with
append(contentsOf: repeatElement(repeating, count: count))
For RangeReplaceableCollection.append(count: generator:)
, it would seem better to make something like
func generateElements<T>(count n: Int, generator: @escaping () ??? -> T) -> Generated<T>
and carry that as a Sequence
to use with the existing initializers, append
, insert
, and replace
methods that take sequences. The problem that the throws
/rethrows
system can't work because we cascade the throw-ability differently. We would have to make different overloads; or keep the way you use the rethrow
system here. I think we need to work on the side-effect design some more, like I read a Microsoft paper once (from a link from a post on this forum) with a programming language that generalized exception propagation for any side effect.
The extension for Set
can be implemented with existing members once a generator Sequence
is done. (The update(count: capacityIncrease: generator)
method can be reworked with union(_:)
or formUnion(_:)
. The initializer can be replaced with the existing sequence-taking one.)
The three members of the second extension to RangeReplaceableCollection
can be reworked with existing members once a generator Sequence
is done. The prepend
method should be a general extension method with Sequence
and single-Element
versions, like insert
and append
. There is a second concern: the very use of Index
in the closures is fundamentally broken.
- The operations to add/remove/replace elements can invalidate every element's index, so use of
at
's value after the first call toinsert
is a fatal error right there. - The index of a new element is determined solely by the collection. You cannot guess a new element's index from an existing element's index. (And from the previous point, said existing element's index value was decertified when the insert occurred!)
Even if they worked in testing, their core code violates the rules of RangeReplaceableCollection
.
The extension for Dictionary
isn't illegal since it manipulates Key
s instead of Index
es. But its two members can be reworked with a map.
public extension Dictionary where Key: Strideable {
@discardableResult @inlinable
mutating func insert(count: Int, fromKey: Key, generator: (_ key: Key) throws -> Value) rethrows -> Dictionary<Key, Value> {
precondition(count >= 0, "Negative count: \(count).")
reserveCapacity(self.count + count)
try merge((0..<count).map { fromKey.advanced(by: $0 as! Key.Stride) }.map { ($0, try generator($0)) }) { $1 }
return self
}
@inlinable
init(count: Int, fromKey: Key, generator: (_ key: Key) throws -> Value) rethrows {
try self.init(uniqueKeysWithValues: (0..<count).map { fromKey.advanced(by: $0 as! Key.Stride) }.map { ($0, try generator($0)) })
}
}