Fibonacci Sequence using iterator protocol

Iterator protocol in Swift is the driving force behind the for-in loop of any sequence. Any type confirming to Sequence protocol such as an Array should provide its own iterator.
So the implementation of the Fibonacci sequence would look like this
class FibonacciSequence:Sequence {
func makeIterator() -> FibonacciIterator {
FibonacciIterator()
}
}Iterator keeps track of its iteration process and returns one element at a time as it advances through the sequence. Iterator has to implement next() function which returns the next element of the sequence.
struct FibonacciIterator:IteratorProtocol {
var (firstNumber, secondNumber) = (0, 1) mutating func next() -> Int? {
(firstNumber, secondNumber) =
(secondNumber, firstNumber + secondNumber)
return firstNumber
}
}
next() function calculates the next step or next number in the Fibonacci sequence.
Now we can use FibonacciSequence in the for-in loop
let fibonacciSequence = FibonacciSequence().prefix(5)
for number in fibonacciSequence {
print(number)
}
//prints 1 1 2 3 5Notice that FibonacciIterator is infinite iterator and has no termination condition. Sequence can be terminated with the condition such as maximum length of the sequence or any other termination condition.
For example, we could generate Fibonacci numbers up to 50 with the following code
let fibonacciSequence = FibonacciSequence().prefix { $0 < 50 }If you are implementing an iterator and wants to control termination of sequence at the iterator level, add a termination condition
struct FibonacciIterator: IteratorProtocol { var (firstNumber, secondNumber) = (0, 1) var maxLength:Int = 0
var currentLength:Int = 0 init(maxLength:Int) {
self.maxLength = maxLength
} mutating func next() -> Int? {
guard currentLength < maxLength else {
return nil
}
(firstNumber, secondNumber) =
(secondNumber, firstNumber + secondNumber)
currentLength += 1
return firstNumber
}
}
Above FibonacciIterator takes the maximum number in its initializer and returns nil after the maximum number of iterations reached.
let fibonacciSequence = AnySequence{ FibonacciIterator(maxLength:6)}for number in fibonacciSequence {
print(number)
}
//prints 1,1,2,3,5,8
Implementing custom sequence with the help of the iterator protocol is useful especially when we want to implement lazy loading.
