符合Swift中的Sequence和IteratorProtocol

时间:2016-11-18 04:44:34

标签: swift swift3 sequence swift-protocols

我正在尝试编写自己的IndexingIterator版本,以增加对Sequence的理解。我没有在我的struct中为associatetype Iterator指定任何类型。但是,编译器没有抱怨这一点,我得到了makeIterator的默认实现。

以下是我的代码:

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() 

我认为Sequence上必须有一些扩展,它们会添加默认实现。因此,我在Sequence.swift中搜索了它,但却发现了这一点。

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

我以为会是这样的:

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

我是否遗漏了某些内容,或者我误解了扩展名?

3 个答案:

答案 0 :(得分:1)

看起来亚历山大的回答是正确的。这是一个简化版本,不使用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()

答案 1 :(得分:0)

类型别名不是必需的,因为Element关联类型是从next()的实现中推断出来的。

这是一个简单的例子:

protocol ResourceProvider {
    associatedtype Resoruce
    func provide() -> Resoruce;
}

struct StringProvider {
    func provide() -> String { // "Resource" inferred to be "String"
        return "A string"
    }
}

答案 2 :(得分:0)

您可以先编写自己的Iterator,然后将其与IteratorProtocol对话,然后将您需要的内容写入Sequence

确保您必须实施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)
        }
    }