Yieldы

Потихоньку привыкаем к тому, что они уже есть :slight_smile:

Пример 1.

function Gen: sequence of (integer,integer,integer);
begin
  for var i:=1 to 9 do
  for var j:=1 to 9 do
    yield (i,j,i*j);
end;

begin
  Gen.Println
end.

Пример 2.

function Fib: sequence of integer;
begin
  var a := 1;
  var b := 1;
  yield a;
  while True do
  begin
    (a,b) := (b,a+b);
    yield a;
  end;
end;

begin
  Fib.Take(10).Println
end.

Пример 3.

function Filter<T>(seq: sequence of T; p: T->boolean): sequence of T;
begin
  foreach var x in seq do
    if p(x) then
      yield x
end;

begin
  Filter(Range(1,10), x->x mod 2 = 0).Println;
end.

Пример 4.

type
  Node<T> = auto class
    data: T;
    left, right: Node<T>;
  end;
  
function CreateTree(n: integer): Node<integer>;
begin
  if n <= 0 then
    Result := nil
  else
    Result := new Node<integer>(
      Random(100), 
      CreateTree((n-1) div 2), 
      CreateTree(n - 1 - (n-1) div 2));
end;

function Infix<T>(root: Node<T>): sequence of T;
begin
  if root.left<>nil then 
    foreach var x in Infix(root.left) do
      yield x;
  yield root.data;
  if root.right<>nil then 
    foreach var y in Infix(root.right) do
      yield y;
end;  

begin
  var r := CreateTree(10);
  InfixPrintTree(r).Println;
end.

Пример 5.

// Все перестановки
const n = 3;

var a: array of integer;

function Perm(a: array of integer; m: integer): sequence of array of integer;
begin
  if m=1 then
    yield a;
  for var i:=0 to m-1 do
  begin
    Swap(a[i],a[m-1]);
    foreach var x in Perm(a,m-1) do
      yield x;
    Swap(a[i],a[m-1]);
  end;
end;

begin
  a := Range(1,n).ToArray; 
  Perm(a,n).Println(NewLine);
end. 

Думаю, неподготовленному человеку совершенно неясно по этим примерам, какой прок в йлдах. Память экономится? А в какой задаче это действительно важно?

Это пока для подготовленных :slight_smile:

Вот еще один прелестный пример:

uses GraphABC;

function RandomPoints: sequence of Point;
begin
  while True do
    yield Pnt(Random(Window.Width),Random(Window.Height));
end;

begin
  RandomPoints.ForEach(p->Circle(p.x,p.y,Random(3,6)));
end.

Реализованы yield sequence. Вот пара примеров:

function f: sequence of real;
begin
  yield sequence Seq(1,2,3);
  yield 4;
end;

begin
  f.Println;
end.

Обход бинарного дерева

type
  Node<T> = auto class
    data: T;
    left, right: Node<T>;
  end;

function CreateTree(n: integer): Node<integer>;
begin
  if n <= 0 then
    Result := nil
  else
    Result := new Node<integer>(
      Random(100), 
      CreateTree((n - 1) div 2), 
      CreateTree(n - 1 - (n - 1) div 2));
end;

function InfixPrintTree<T>(root: Node<T>): sequence of T;
begin
  if root = nil then exit;
  yield sequence InfixPrintTree(root.left);
  yield root.data;
  yield sequence InfixPrintTree(root.right);
end;

begin
  var r := CreateTree(10);
  InfixPrintTree(r).Println;
end.