protocol MyIteratorProtocol<Element> { associatedtype Element mutating func next() -> Element? } protocol MySequence<Element> { associatedtype Element associatedtype Iterator: MyIteratorProtocol<Element> func makeIterator() -> Iterator // func makeIterator() -> any MyIteratorProtocol<Element> } protocol MyCollection<Element>: MySequence { associatedtype Index: Comparable associatedtype Indices: MyCollection where Indices.Element == Index associatedtype SubSequence: MyCollection where SubSequence.Element == Element, SubSequence.Index == Index, SubSequence.SubSequence == SubSequence subscript(index: Index) -> Element { get } subscript(range: Range<Index>) -> SubSequence { get } var indices: Indices { get } }
struct Pair<Element>: MySequence { var elements: (Element, Element) func makeIterator() -> some MyIteratorProtocol<Element> { PairIterator(pair: self) } } struct PairIterator<Element>: MyIteratorProtocol { var pair: Pair<Element> var index: Int = 0 mutating func next() -> Element? { defer { index += 1 } switch index { case 0: return pair.elements.0 case 1: return pair.elements.1 case _: return nil } } }
let pair: Pair<Int> = .init(elements: (2, 3)) //for element in pair { // print(element) //} var iterator = pair.makeIterator() while let element = iterator.next() { print(element) }
// ジェネリクス地獄 class MyIteratorProtocol<Element> { func next() -> Element? { fatalError() } } class MySequence<Element, Iterator: MyIteratorProtocol<Element>> { func makeIterator() -> Iterator { fatalError() } } class MyCollection< Element, Index: Comparable, IndicesIndex, IndicesIterator: MyIteratorProtocol<Index>, Indices: MyCollection< Index, IndicesIndex, IndicesIterator, >, Iterator: MyIteratorProtocol<Element>, SubSequenceIterator: MyIteratorProtocol<Element>, SubSequence: MyCollection< Element, Index, SubSequenceIterator, SubSequenceIterator, SubSequence > >: MySequence<Element, Iterator> { subscript(index: Index) -> Element { fatalError() } subscript(range: Range<Index>) -> SubSequence { fatalError() } var indices: Indices { fatalError() } }