Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

conforming to Sequence and IteratorProtocol in Swift

I am trying to write my own version of IndexingIterator to increase my understanding of Sequence. I haven't assign any type to associatetype Iterator in my struct. However, the complier doesn't complain about that and I get a default implementation of makeIterator.

Following are my codes:

struct __IndexingIterator<Elements: IndexableBase>: Sequence, IteratorProtocol {
    mutating func next() -> Elements._Element? {
        return nil
    }
}
let iterator = __IndexingIterator<[String]>()
// this works and returns an instance of __IndexingIterator<Array<String>>. why?
iterator.makeIterator() 

I think there must be some extensions on Sequence which add the default implementation. Thus, I searched it in Sequence.swift and only found this.

extension Sequence where Self.Iterator == Self, Self : IteratorProtocol {
  /// Returns an iterator over the elements of this sequence.
  public func makeIterator() -> Self {
    return self
  }
}

I thought it would be like this:

extension Sequence where Self: IteratorProtocol {
    typealias Iterator = Self
    ...
}

Did I miss something or I misunderstood the extension?

like image 831
Evan Avatar asked Nov 18 '16 04:11

Evan


People also ask

How do you conform a sequence protocol?

To add Sequence conformance to your own custom type, add a makeIterator() method that returns an iterator. Alternatively, if your type can act as its own iterator, implementing the requirements of the IteratorProtocol protocol and declaring conformance to both Sequence and IteratorProtocol are sufficient.

What is sequence and iterator?

Sequences provide access to their elements by creating an iterator, which keeps track of its iteration process and returns one element at a time as it advances through the sequence. Whenever you use a for - in loop with an array, set, or any other collection or sequence, you're using that type's iterator.

What is iterator protocol in Python?

Iterators in Python Iterator in Python is simply an object that can be iterated upon. An object which will return data, one element at a time. Technically speaking, a Python iterator object must implement two special methods, __iter__() and __next__() , collectively called the iterator protocol.


2 Answers

It looks like Alexander's answer is correct. Here's a boiled down version, without using Sequence:

protocol MySequence {
    associatedtype Iterator: IteratorProtocol
    func maakeIterator() -> Iterator
}

extension MySequence where Self.Iterator == Self, Self : IteratorProtocol {
    /// Returns an iterator over the elements of this sequence.
    func maakeIterator() -> Self {
        return self
    }
}

struct __IndexingIterator<Element>: MySequence, IteratorProtocol {
    mutating func next() -> Element? {
        return nil
    }
}

let iterator = __IndexingIterator<[String]>()
iterator.maakeIterator()
like image 182
Chris Eidhof Avatar answered Oct 22 '22 22:10

Chris Eidhof


You can write your own Iterator which confrom to IteratorProtocol first, then write what you need confrom to Sequence.

Make sure that you have to implement requried func.

   struct IteratorTest : IteratorProtocol {
        typealias Element = Int

        var count : Int

        init(count :Int) {
            self.count = count
        }

        mutating func next() -> Int? {
            if count == 0 {
                return nil
            }else {
                defer {
                    count -= 1
                }
                return count;
            }
        }
    }

    struct CountDown : Sequence {
        typealias Iterator = IteratorTest
        func makeIterator() -> IteratorTest {
            return IteratorTest.init(count: 10)
        }
    }
like image 27
wind Avatar answered Oct 22 '22 23:10

wind