Minimal working IteratorProtocol / Sequence in Swift 3

It was very difficult for me to find a “working documentation” for using Sequence / IteratorProtocol in Swift 3. Several tutorials / articles seem to be for older Swift.

Imagine a game with a doubly linked list class 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 } 

I believe the following is a simple (?), Correct way to do this in one word, using the DLList in the for structure.

Step 1, DLList compatible with DLList: Sequence

 public class DLList:Sequence { // toy linked list class here public func makeIterator() -> DLListIterator { return DLListIterator(self) } } 

It would seem that all you need to do is add a call to makeIterator .

Step 2, write your iterator, matches IteratorProtocol

Since the class is DLList, we will call it DLListIterator. It would seem that,

1, you should have "init", which basically takes the group class in question

2, you should have a next call, which should return one of the “things” that are magically related to your group class.

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

This works great. those. now you can go

 var d:DLList = DLList() for n in d { print or whatever n } 

you can use e = d.filter( {d.item blah} ) , etc. - well.

The question is a lot of talk about related types . In part 1, do you explicitly specify / add a "related type" somehow? Even if he did not explicitly demand , how would you do it explicitly? What the hell is a related type business?

The question is, in the second part, I am completely puzzled by how he "knows" that Node is a "thing" related to a DLList. Is there a way to make this explicit, or what I don't understand?

Quickness In addition, all this does not look very Swifty. It seems incredible to do everything just to add an iterator output. Is there a faster way for a real class in Swift3? (Not such a stupid example as "countdown numbers.")

The final question . I am pleased to note that the above also allows .filter. Actually, my example is “complete” - can I now do everything “iterator-wise” with a DLList, which can be done normally in Swift - maybe I “forgot some functions” or? Does DLList need to do a really good iterator yet?

+6
source share
1 answer

All this works fine with type inference (a really strong thing in Swift).

eg. IteratorProtocol has only one requirement, i.e. the next() -> Element? method next() -> Element? . Here is what you can see if you just Cmd-click on IteratorProtocol in Xcode:

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

So, if you declare a type corresponding to IteratorProtocol and provide an implementation of some next() -> Foo? then Swift immediately reports that Foo should be an Element .

You can, of course, make an explicit declaration through:

 public class DLListIterator: IteratorProtocol { public typealias Element = Node public func next() -> Element? { // ... } } 

And yes, once you have implemented both ( Sequence and Iterator , that is), you can do whatever the other sequences can do. All this thanks to the implementation of the default protocol.

Is this all a template to match Sequence you need to provide makeIterator() , which in turn must provide next() , is Swifty or not .. I think this is something more based on. Sometimes you can implement Sequence without moving on to implementing IteratorProtocol (for example, when implementing a wrapper). So, the split makes sense to me.

+3
source

Source: https://habr.com/ru/post/1011899/


All Articles