Swift 3中最小的工作IteratorProtocol/Sequence

Fat*_*tie 8 iterator sequence swift3

我发现在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
    }
Run Code Online (Sandbox Code Playgroud)

我相信以下代表了最简单(?),正确的方法,使其可以,一句话,用DLList在一个for结构.

第1步,让你的DLList符合DLList:Sequence

public class DLList:Sequence
    {
    // toy linked list class here

    public func makeIterator() -> DLListIterator
        {
        return DLListIterator(self)
        }
    }
Run Code Online (Sandbox Code Playgroud)

似乎你所要做的就是添加makeIterator呼叫.

第2步,编写你的迭代器,符合 IteratorProtocol

由于该类是DLList,我们将其称为DLListIterator.看起来似乎是这样

1,你必须有一个"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
        }
    }
Run Code Online (Sandbox Code Playgroud)

这似乎完美无缺.也就是说,你现在可以去了

var d:DLList = DLList()
for n in d
 {
 print or whatever n
 }
Run Code Online (Sandbox Code Playgroud)

你可以使用e = d.filter( {d.item blah} )等等 - 很棒.

问题 - 有很多关于相关类型的讨论.在第1部分中,您是否以某种方式明确声明/添加"关联类型"?即使没有明确要求你会如何明确地做到这一点?这种相关类型的业务到底是什么?

问题 - 在第二部分中,我完全不知道它是如何"知道"Node是与DLList相关的"事物".有没有办法明确表达,或者我不理解什么?

迅捷而且,整个事情看起来不是很迅速.这样做只是为了添加迭代器输出似乎令人难以置信.对于真正的类,在Swift3中有一种更快捷的方式吗?(不是像"倒计时数字"这样的愚蠢的例子.)

最后的问题我高兴地提到上面现在允许和.filter.事实上,我的例子是"完整的" - 我现在可以用DLList做一切"iterator-wise",一个人可以在Swift中正常做 - 我可能"忘记了一些功能"或者?? 在使DLList成为一个非常好的迭代器时还有更多工作要做吗?

cou*_*elk 5

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

例如IteratorProtocol,只有一个要求,那就是next() -> Element?方法。如果只是IteratorProtocol在XCode中单击Cmd,则可以看到以下内容:

public protocol IteratorProtocol {
    associatedtype Element
    public mutating func next() -> Self.Element?
}
Run Code Online (Sandbox Code Playgroud)

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

当然,您可以通过以下方式进行明确的声明:

public class DLListIterator: IteratorProtocol {
    public typealias Element = Node

    public func next() -> Element? {
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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


lbs*_*eek 5

这是我的最小例子

class TestIter: Sequence, IteratorProtocol {
    var mylist:[Int] = [1,2,3,4,5,6]    // contents
    var curPos = 0                      // var for iterator

    func makeIterator() -> TestIter {
        curPos = 0
        return self
    }

    public typealias Element = Int
    func next() -> Element? {
        if curPos < mylist.count {
            let oldPos = curPos
            curPos += 1
            return mylist[oldPos]
        }
        return nil
    }

}

let testIt = TestIter()
for i in testIt {
    print("i:\(i)")
}
Run Code Online (Sandbox Code Playgroud)