Range Over Iterators in Logo

Exemple : Itérer sur des itérateurs

À partir de la version 1.23, ce langage a ajouté le support pour les itérateurs, ce qui nous permet de parcourir quasiment tout !

Voyons de nouveau le type List de l’exemple précédent. Dans cet exemple, nous avions une méthode AllElements qui renvoyait une slice de tous les éléments de la liste. Avec les itérateurs, nous pouvons faire mieux, comme illustré ci-dessous.

import Foundation

struct Element<T> {
    var next: Element?
    var value: T
}

struct List<T> {
    private var head: Element<T>?
    private var tail: Element<T>?

    mutating func push(_ value: T) {
        let newElement = Element(next: nil, value: value)
        if let tail = tail {
            tail.next = newElement
        } else {
            head = newElement
        }
        tail = newElement
    }

    func all() -> AnyIterator<T> {
        var current = head
        return AnyIterator {
            guard let element = current else {
                return nil
            }
            current = element.next
            return element.value
        }
    }
}

func genFib() -> AnyIterator<Int> {
    var a = 1
    var b = 1
    return AnyIterator {
        let temp = a
        a = b
        b = temp + a
        return temp
    }
}

var list = List<Int>()
list.push(10)
list.push(13)
list.push(23)

for element in list.all() {
    print(element)
}

let allElements = Array(list.all())
print("all:", allElements)

for number in genFib() {
    if number >= 10 {
        break
    }
    print(number)
}

Pour itérer sur tous les éléments, nous pouvons utiliser la fonction all de la liste, qui renvoie un itérateur.

for element in list.all() {
    print(element)
}

Les packages comme Array ont un certain nombre de fonctions utiles pour travailler avec des itérateurs. Par exemple, Array prend n’importe quel itérateur et collecte toutes ses valeurs dans une array.

let allElements = Array(list.all())
print("all:", allElements)

Il est aussi possible de créer un itérateur infini, comme celui pour les nombres de Fibonacci ci-dessous :

for number in genFib() {
    if number >= 10 {
        break
    }
    print(number)
}

Une fois que la boucle atteint break ou un retour anticipé, la fonction yield passée à l’itérateur retournera false.