String.Iterator
(неявно) определяется как
typealias Iterator = IndexingIterator<String>
и сообщение об ошибке
Ограниченное расширение должно быть объявлено для неспециализированного универсального типа 'IndexingIterator' с ограничениями, указанными в предложении 'where'
означает, что мы должны определить методы расширения как
extension IndexingIterator where Elements == String { }
В качестве альтернативы (с возрастающей общностью):
extension IndexingIterator where Elements: StringProtocol { }
extension IndexingIterator where Elements.Element == Character { }
Я не нашел способа получить доступ к базовой коллекции (или позиции)
изнутри метода расширения соответствующие члены определены как
«Внутренний»:
public struct IndexingIterator<Elements : Collection> {
internal let _elements: Elements
internal var _position: Elements.Index
// ...
}
То, что вы можете сделать, это передать требуемый элемент в ваш метод «следующего выхода»
либо как сам элемент, либо как предикат:
extension IndexingIterator where Elements.Element == Character {
mutating func next(_ wanted: Character) -> Character? {
while let c = next() {
if c == wanted { return c }
}
return nil
}
mutating func next(where predicate: ((Character) -> Bool)) -> Character? {
while let c = next() {
if predicate(c) { return c }
}
return nil
}
}
Пример использования:
var it1 = "ABCDABCE".makeIterator()
print(it1.next("C") as Any) // Optional("C")
print(it1.next() as Any) // Optional("D")
print(it1.next("C") as Any) // Optional("C")
print(it1.next() as Any) // Optional("E")
print(it1.next("C") as Any) // nil
var it2 = "LINnIIBDDDN".makeIterator()
while let c = it2.next(where: { "Nn".contains($0) }) {
print(c, terminator: ", ")
}
print()
// N, n, N,
Но на самом деле я бы рассмотрел String.Iterator
как IndexingIterator
деталь реализации и вместо этого расширил бы IteratorProtocol
:
extension IteratorProtocol where Element: Equatable {
mutating func next(_ wanted: Element) -> Element? {
while let e = next() {
if e == wanted { return e }
}
return nil
}
}
extension IteratorProtocol {
mutating func next(where predicate: ((Element) -> Bool)) -> Element? {
while let e = next() {
if predicate(e) { return e }
}
return nil
}
}
Это делает его пригодным для произвольных последовательностей. Пример: * +1032 *
var it3 = [1, 1, 2, 3, 5, 8, 13, 21, 34].makeIterator()
while let e = it3.next(where: { $0 % 2 == 0} ) {
print(e, terminator: ", ")
}
print()
// 2, 8, 34,