Range Over Iterators in AngelScript

Starting with version 1.23, the language has added support for iterators, which lets us range over pretty much anything!

Let’s look at the List type from the previous example again. In that example we had an AllElements method that returned a slice of all elements in the list. With iterators, we can do it better - as shown below.

class List<T> {
    element@ head;
    element@ tail;

    void Push(const T &in v) {
        if (tail is null) {
            @head = element(v);
            @tail = head;
        } else {
            @tail.next = element(v);
            @tail = tail.next;
        }
    }

    void All(funcdef bool Yield(const T &in)) {
        element@ e = head;
        while (e !is null) {
            if (!Yield(e.val)) return;
            @e = e.next;
        }
    }
}

class element<T> {
    element@ next;
    T val;

    element(const T &in v) {
        val = v;
    }
}

bool yieldFunc(const int &in val){
    if (val >= 10) return false;
    println(val);
    return true;
}

List<int> lst;
lst.Push(10);
lst.Push(13);
lst.Push(23);

lst.All(yieldFunc);

// Function returning an iterator over Fibonacci numbers:
bool genFib(funcdef bool Yield(const int &in)) {
    int a = 1, b = 1;
    while (true) {
        if (!Yield(a)) return false;
        int c = a + b;
        a = b;
        b = c;
    }
    return true;
}

bool fibYieldFunc(const int &in val){
    if (val >= 10) return false;
    println(val);
    return true;
}

genFib(fibYieldFunc);

The code above demonstrates how to define a List class and an element class in AngelScript. These classes are augmented with methods to push elements into the list and iterate over its elements using a functional approach with yield.

Iteration doesn’t require an underlying data structure and doesn’t even have to be finite! Here’s a function returning an iterator over Fibonacci numbers: it keeps running as long as yield keeps returning true.

Since List.All returns an iterator, we can use it in a regular range loop. Moreover, you can see how a generator function like genFib() provides an infinite sequence of Fibonacci numbers, respecting the yield function to manage flow control.

Running this AngelScript code will mimic the behavior described, utilizing idiomatic expressions for AngelScript. This approach helps maintain readability and leverages the language’s features effectively.