Skip to the content.

Итераторы

Итераторы в NewLang, как и в остальных языках программирования, предназначены для перебора элементов. Но, в отличии от итераторов в С++, итераторы NewLang являются самостоятельными объектами, а не указателями на отдельные элементы объекта-контейнера. Итераторы NewLang поддерживают фильтрацию элементов по имени за счет использования функций обратного вызова.

Для работы с итераторами используется следующий синтаксис:

Примеры создания итераторов с разными фильтрами отбора данных:

iter := dict ? ("name"); # Создание итератора для значений с указанным именем
iter := dict ? ("regex."); # Создание итератора для полей с префиксом "regex"

# Чистая функция для фильтрации по значению
filter(value) :- { $value && $value < 10; }; 
iter := dict ? (filter); # Создание итератора для значений меньше 10

equal(value, arg) := { $value == arg }; # Обычная функция
iter := dict ? (equal, 100); # Создать итератор только для значений 100

Оператор перебора элементов итератора ! возвращает текущий элемент и сдвигает указатель на следующий. Точнее, на количество считанных элементов, так как прочитать элементы из итератора можно не только по одному, а и заданными порциями, например по 10 за один раз, iter ! (10);.

Если указать количество считываемых элементов !(0), то будет возвращен сам элемент, но для значений отличных от нуля будет возвращаться не элемент данных, а словарь с данными, считанными из итератора. Из-за этого операторы ! и !(0) НЕ эквивалентны, т.к. по разному обрабатывают конец данных.

Лучше всего это показать на примерах для словаря с пятью элементами:

dict := (1,2,3,4,5,)?; # Создать итератор для словаря

dict!; # -> 1
dict!; # -> 2
dict!; # -> 3
dict!; # -> 4
dict!; # -> 5
dict!; # -> будет исключение "конец итератора"

# Но
dict !(0); # -> (1,)
dict !(0); # -> (2,)
dict !(0); # -> (3,)
dict !(0); # -> (4,)
dict !(0); # -> (5,)
dict !(0); # -> (,) - вернется пустой словарь

Так же для чтения итератора можно указывать и отрицательное количество элементов. В этом случае будет возвращаться словарь всегда указанного размера, но элементы в словаре будут присутствовать только в случае чтения реальных данных из итератора:

dict := (1,2,3,4,5,) ?; # Итератор для словаря с пятью элементами

dict !(3); # -> (1,2,3,)
dict !(3); # -> (4,5,)
dict !(3); # -> (,)

# Но
dict !(-3); # -> (1,2,3,)
dict !(-3); # -> (4,5, :IteratorEnd)
dict !(-3); # -> (:IteratorEnd, :IteratorEnd, :IteratorEnd)