Последовательности

Последовательность sequence of T — это набор элементов, которые можно перебирать один за другим. Для перебора обычно используют цикл foreach или методы последовательностей.

Массивы, списки и множества являются последовательностями.

Описание последовательности

Переменная типа sequence of T может хранить последовательность элементов заданного типа.

begin
  var s: sequence of integer := Arr(1..5);

  s.Print;
  Println(s.Count);
end.

Результат:

1 2 3 4 5
5

Разные коллекции как последовательности

Переменной типа sequence of T можно присваивать массив, список или множество с элементами подходящего типа.

begin
  var s: sequence of integer;

  s := [1,2,3];
  s.Println;

  s := Lst(4,5,6);
  s.Println;

  s := SetOf(7,8,9);
  s.Println;
end.

Результат:

1 2 3
4 5 6
7 8 9

Цикл по последовательности

Цикл foreach используется для последовательного перебора всех элементов sequence of T.

begin
  var s: sequence of integer := Arr(1..5);

  foreach var x in s do
    Print(x*x);
end.

Результат:

1 4 9 16 25

Последовательность как параметр

Последовательность может быть параметром процедуры или функции. Параметру типа sequence of T можно передать массив, список, множество или другую последовательность с элементами подходящего типа.

procedure PrintSequence<T>(s: sequence of T);
begin
  foreach var x in s do
    Print(x);
  Println;
end;

begin
  var a := [1,2,3];
  var L := Lst(4,5,6);
  var s := SetOf(7,8,9);

  PrintSequence(a);
  PrintSequence(L);
  PrintSequence(s);
end.

Результат:

1 2 3
4 5 6
7 8 9

Основные методы последовательностей

К последовательностям можно применять такие методы как Print и Count.

begin
  var s: sequence of integer := Arr(1..10);

  s.Print;
  Println;
  Println(s.Count);
end.

Результат:

1 2 3 4 5 6 7 8 9 10
10

Целочисленный диапазон

Диапазон .. целых значений можно использовать как последовательность и применять к нему методы последовательностей.

begin
  (1..10).Print;
end.

Результат:

1 2 3 4 5 6 7 8 9 10

Генератор Range

Функция Range создаёт последовательность целых чисел. В отличие от массива или списка, её элементы не хранятся заранее, а вычисляются по мере перебора.

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

begin
  Range(1,10).Print;
end.

Результат:

1 2 3 4 5 6 7 8 9 10

Range с шагом

Третий параметр Range задаёт шаг изменения значений последовательности.

begin
  Range(1,10,2).Print;
end.

Результат:

1 3 5 7 9 

Вещественный Range

Range можно использовать и для генерации последовательности вещественных чисел.

begin
  Range(1,3,0.2).Print;
end.

Результат:

1 1.2 1.4 1.6 1.8 2 2.2 2.4 2.6 2.8 3

Равномерное разбиение отрезка

PartitionPoints создаёт заданное количество равномерно расположенных точек на отрезке.

begin
  PartitionPoints(1,3,10).Print;
end.

Результат:

1 1.2 1.4 1.6 1.8 2 2.2 2.4 2.6 2.8 3

Преобразование последовательности в коллекцию

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

begin
  var s: sequence of integer := 1..5;

  var a := s.ToArray
  a[0] := 777;
  a.Println;
  s.ToList.Println;
  s.ToSet.Print;
end.

Результат:

777 2 3 4 5
1 2 3 4 5
1 2 3 4 5

Пользовательский генератор последовательности

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

function Squares(n: integer): sequence of integer;
begin
  for var i := 1 to n do
    yield i * i;
end;

begin
  Squares(5).Print;
end.

Результат:

1 4 9 16 25

Бесконечная последовательность

Генератор может создавать бесконечную последовательность. Все её элементы невозможно заранее сохранить в памяти — их бесконечно много, поэтому они вычисляются по мере перебора.

Метод Take(n) позволяет ограничить бесконечную последовательность, взяв только первые n элементов. Если этого не сделать, бесконечная последовательность будет выводиться очень долго :)

function NaturalNumbers: sequence of integer;
begin
  var n := 1;
  while true do
  begin
    yield n;
    n += 1;
  end;
end;

begin
  NaturalNumbers.Take(10).Print;
end.

Результат:

1 2 3 4 5 6 7 8 9 10