【问题标题】:conforming to Sequence and IteratorProtocol in Swift符合 Swift 中的 Sequence 和 IteratorProtocol
【发布时间】:2017-04-01 20:37:37
【问题描述】:

我正在尝试编写自己的IndexingIterator 版本以增加我对Sequence 的理解。我没有在我的结构中为 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
    ...
}

我是否遗漏了什么或者我误解了扩展程序?

【问题讨论】:

    标签: swift swift3 sequence swift-protocols


    【解决方案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()
    

    【讨论】:

      【解决方案2】:

      您可以先编写自己的迭代器,将其转换为IteratorProtocol,然后将您需要的转换为Sequence

      确保您必须实现所需的功能。

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

      【讨论】:

        【解决方案3】:

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

        这是一个简单的例子:

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

        【讨论】:

        • 我同意你的例子,但我认为它不能解释我的问题。我认为IteratorProtocol中的关联类型Element可以推断为_IndexableBase._Element,但无法推断Sequence中的关联类型Iterator,因为我对__IndexingIterator的定义缺少Iterator的类型分配。我需要对此作出解释。
        • 您展示的那个扩展(倒数第二个代码 sn-p)定义了既是序列又是积分器的类型的默认实现。默认情况下,此扩展使其符合Sequence,通过将自身返回为makeIterator()__IndexingIterator 符合标准,因为它既是序列又是迭代器。结果,它获得了makeIterator 的默认实现。此默认实现返回 Self 类型,在此上下文中解析为 __IndexingIterator
        • 编译器也知道makeIterator的返回类型是关联类型Iterator,所以把2和2放在一起得出Iterator__IndexingIterator
        • Interestingggg 这是一个很好的观点。我需要考虑一下这个
        • 您说“__IndexingIterator 符合标准,因为它既是序列又是迭代器”,但我对此表示怀疑。扩展有一个前提条件Self.Iterator == Self,这就是我的困惑所在。你能解释一下__IndexingIterator是如何被证明是Self.Iterator == Self吗?
        猜你喜欢
        • 2021-03-05
        • 2018-08-26
        • 1970-01-01
        • 1970-01-01
        • 2023-01-08
        • 1970-01-01
        • 1970-01-01
        • 2021-02-18
        • 1970-01-01
        相关资源
        最近更新 更多