Генератор (програмування)

Матеріал з Вікіпедії — вільної енциклопедії.
Перейти до навігації Перейти до пошуку

Генератор — в інформатиці, це підпрограма, що контролює ітерації в циклі.

Генератор є підвидом ітератора.

Різниця між ітератором і генератором:

  • Ітератор проходить по колекції по одному елементу за раз.
  • Генератор генерує елементи послідовності по одному елементу за раз.

Генератор може бути реалізований у вигляді наступних конструкцій потоку керування як:

Генератор є частковим випадком співпрограми, оскільки завжди повертає керування до того коду, який його викликав.

Приклади в різних мовах програмування[ред. | ред. код]

C#[ред. | ред. код]

public static IEnumerable<int> GetEven(IEnumerable<int> numbers)
{
    foreach (int i in numbers)
        if ((i % 2) == 0)
            yield return i;
}

F#[ред. | ред. код]

seq
{
    for b in 0 .. 25 do
        if b < 15 then
            yield b * b
}

C++[ред. | ред. код]

C++11 дозволяє застосовувати foreach цикли до будь-якого класу, що надає функції begin та end. Отже, можливо написати подібний до генератора клас визначивши обидва ці методи і методи ітератора (operator!=, operator++ і operator*) в одному класі. Наприклад, можливо написати таку програму:

#include <iostream>
int main()
{
    for (int i: range(10))
    {
        std::cout << i << std::endl;
    }
    return 0;
}

Просте втілення класа range виглядало б так:

class range
{
private:
    int last;
    int iter;

public:
    range(int end):
        last(end),
        iter(0)
    {}

    // Повертають ітератор
    const range& begin() const { return *this; }
    const range& end() const { return *this; }

    // Функції ітератора
    bool operator!=(const range&) const { return iter < last; }
    void operator++() { ++iter; }
    int operator*() const { return iter; }
};

В Microsoft Visual C++ 2015 реалізовані деякі пропозиції для C++17

#include <experimental/generator>

using namespace std::experimental;

inline generator<int> values()
{
	for (int i = 0; i < 100; ++i)
	{
		__yield_value i*i;
	}
}

Можливо писати в стилі, який через вкладеність викликів, читатиметься знизу вверх:

	auto seq = take(5
				,transform([](int x) {return x*x;}
				,where([](int x) {return x % 2 == 0;}
				,fibonacci()
				)));

	for (auto i : seq)
		printf("%d ", i);

Посилання[ред. | ред. код]