我发现很难找到在Swift 3中使用Sequence/IteratorProtocol的“工作文档”。那里的一些教程/文章似乎适用于较早的Swift。
想象一下一个名为DLList的玩具双向链接列表类...

public class Node
    {
    // whatever "thing" you have a group of, this is that "thing"
    }
public class DLList
    {
    // toy linked list class here
    // so this is a group of "node" in this example
    }
我相信以下内容代表了最简单的(?)正确方法,即可以一句话在DLList结构中使用for
步骤1,使您的DLList符合DLList:Sequence
public class DLList:Sequence
    {
    // toy linked list class here

    public func makeIterator() -> DLListIterator
        {
        return DLListIterator(self)
        }
    }
似乎您所需要做的就是添加makeIterator调用。
步骤2,编写您的迭代器,符合IteratorProtocol由于该类是DLList,因此我们将其称为DLListIterator。看来
1,您必须有一个“init”,该“init”基本上可以使用相关的组
2,您必须有一个next调用,该调用必须返回与组类魔术相关的“事物”之一。
public class DLListIterator:IteratorProtocol
    {
    var dll:DLList  // you must know the group in question
    var pointer:Node?  // you must know where you are

    init(_ dll:DLList)
        {
        // so note those two items
        self.dll = dll
        self.pointer = dll.firstOne
        }

    public func next() -> Node?
        {
        // return the next one; careful to return nil at end.
        let thisOne = self.pointer
        self.pointer = self.pointer?.nextOne
        return thisOne
        }
    }
这似乎确实工作正常。即,您现在可以
var d:DLList = DLList()
for n in d
 {
 print or whatever n
 }
您可以使用e = d.filter( {d.item blah} )等-太好了。
问题-关于关联类型的讨论很多。在第1部分中,您是否以某种方式明确声明/添加了“关联类型”?即使没有明确要求,您将如何明确地执行?这个相关类型的业务到底是什么?
问题-在第二部分中,我完全迷惑了它如何“知道” Node是与DLList相关的“事物”。有没有办法使之明确,或者我不明白什么?
迅捷此外,整个事情似乎并不十分迅捷。仅仅添加迭代器输出似乎很难做到。在Swift3中,对于真实的类,有一种更简单的方法吗? (不是一个愚蠢的例子,例如“倒数”。)
最后一个问题我很高兴地提到以上内容现在允许和.filter。实际上,这是我的示例“完成”-我现在可以使用DLList在“迭代器方式”上做所有事情,而在Swift中可以正常执行吗?使DLList成为真正好的迭代器还有更多工作要做吗?

最佳答案

通过类型推断(在Swift中确实很强大),所有这些都可以很好地工作。

例如。 IteratorProtocol仅具有一个要求,即next() -> Element?方法。如果您仅单击CCode并单击XCode中的IteratorProtocol,就会看到以下内容:

public protocol IteratorProtocol {
    associatedtype Element
    public mutating func next() -> Self.Element?
}

因此,如果您声明一个符合IteratorProtocol的类型并提供某种next() -> Foo?的实现,则Swift会立即推断Foo必须是Element

当然,您可以通过以下方式进行明确的声明:
public class DLListIterator: IteratorProtocol {
    public typealias Element = Node

    public func next() -> Element? {
        // ...
    }
}

而且,是的,一旦实现了两者(即SequenceIterator),您就可以完成其他Sequence可以完成的所有工作。这一切都要归功于默认协议(protocol)的实现。

为了符合Sequence而需要提供makeIterator(),而又必须提供next()的所有样板,是否都是Swifty。有时,您可以执行Sequence,而不必执行IteratorProtocol(例如,当实现包装器时)。因此,拆分对我来说确实有意义。

关于iterator - Swift 3中的最小工作IteratorProtocol/Sequence,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40350731/

10-10 04:47