The use of AnyIterator and AnySequence in Swift

First of all, let's take a look at some methods introduced to us in Apple's official documents

The first one is about the initialization method of AnyIterator. The official explanation is to create an iterator that wraps the given closure in its next () method. So the following example initializes AnyIterator for the next method

init(_body: @escaping () -> AnyIterator.Element?)

Then let's look at the example

var x = 7
let iterator: AnyIterator<Int> = AnyIterator {
    defer { x += 1 }
    return x < 15 ? x : nil
}
let a = Array(iterator)
// a == [7, 8, 9, 10, 11, 12, 13, 14]

So we can know to return the elements we want to return to the iterator until nil

Let's look at our AnySequence initialization method, which is called above

init<I>(_makeUnderlyingIterator: @escaping () -> I) where Element == I.Element, I : IteratorProtocol

Method 1: then we define an iterator that complies with both iterator protocol and Sequence protocol

struct MyIterator<Element>:IteratorProtocol, Sequence  {

    //closure
    var base:()->Element?

    init(_ body: @escaping () -> Element?)
    {   
        //Closure saved
        base = body

    }
    //WrittennextMethod
    func next() -> Element?
    {
        return base()

    }

}

In the outside world, we can create an iterator by ourselves. A call to the next method is equivalent to a call to the closure saved in the iterator, and our for in loop. As long as for in is an object that follows the Sequence protocol, it can use the for in loop to iterate. Its essence is to call the next() method

        var x = 7

        let iterator:MyIterator<Int> = MyIterator {
            defer { x += 1 }
            return x < 15 ? x : nil
        }

        print("\(iterator.next())")
          print("\(iterator.next())")

        for a in iterator {
            print(a)
        }

The output is as follows

Method 2: we can also wrap the iterator into the array and then traverse the output

    for a in Array(iterator)
        {
            print(a)
        }

Method 3: another implementation method of iterator, the MyIterator structure follows the Sequence protocol and implements the makeIterator() method

struct MyIterator<Element>:Sequence
{

    public func makeIterator() -> AnyIterator<Int> {
        var idx = 0
        return AnyIterator {
            if idx >= 5 {
                return Optional<Int>.none
            } else {
                //Otherwise, the corresponding value is returned
                idx += 1
                return idx
            }
        }
    }
}

On the outside, we can directly put the container that we have complied with the Sequence protocol into Array, and then call the for -in loop to traverse it.

    let iterator = MyIterator<Int>()

        for a in Array(iterator)
        {
            print(a)
        }

        for a in Array(iterator)
        {
            print(a)
        }
    }

Method 4: we can use the following method to output until nil

 var idx = 1;

        var base:()->Int? = {

            defer {
                idx += 1
            }
            return idx < 5 ? idx : nil
        }

        let sequenc = AnySequence{

            AnyIterator {

                base()
            }
        }

        for a in sequenc {
            print(a)
        }

    }

Added by mandred on Mon, 06 Jan 2020 21:20:49 +0200