我发现在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
。
public class DLList:Sequence
{
// toy linked list class here
public func makeIterator() -> DLListIterator
{
return DLListIterator(self)
}
}
您似乎只需要添加makeIterator
来电。
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
}
}
这似乎完美无缺。即,你现在可以去
var d:DLList = DLList()
for n in d
{
print or whatever n
}
你可以使用e = d.filter( {d.item blah} )
等等 - 很棒。
问题 - 有很多关于关联类型的讨论。在第1部分中,您是否以某种方式明确声明/添加“关联类型”?即使没有明确要求你会如何明确地执行?这种相关类型的业务到底是什么?
问题 - 在第二部分中,我完全不知道它是如何“知道”Node是与DLList相关的“东西”。有没有办法明确,或者我不理解?
迅捷而且,整个事情看起来并不是非常迅速。这样做只是为了添加迭代器输出似乎令人难以置信。对于真正的类,在Swift3中有一种更快捷的方式吗? (不是像“倒计时数字”这样的愚蠢的例子。)
最后的问题我高兴地提到上面现在允许和.filter。事实上,我的例子是“完整的” - 我现在可以用DLList做一切“iterator-wise”,一个人可以在Swift中正常做 - 我可能“忘记了一些功能”或者??在使DLList成为一个非常好的迭代器时还有更多工作要做吗?
答案 0 :(得分:4)
这一切都很适合通过类型推断(在Swift中非常强大的东西)。
E.g。 IteratorProtocol
只有一个要求,即next() -> Element?
方法。如果你只是点击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? {
// ...
}
}
而且,是的,一旦你实现了(Sequence
和Iterator
,那就是)你可以做其他序列可以做的所有事情。所有这一切都要归功于默认的协议实现。
为了符合Sequence
您需要提供的makeIterator()
,所有这些样板是否需要提供next()
,是不是Swifty ..我想这个是更多基于意见的东西。有时,您可以实现Sequence
而无需实现IteratorProtocol
(例如,当您实现包装器时)。因此,拆分确实对我有意义。
答案 1 :(得分:1)
这是我的最小例子
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)")
}