Generator (informatika)
<s>U računarstvu, generator je specijalni potprogram koji može biti upotrebljen za kontrolu iteracijskog ponašanja ponavljanja .</s><s>U suštini, svi generatori su iteratori.</s><s>Generartor je veoma sličan funkciji koja vraća niz, u kojoj generator ima parametre, koja se može pozvati, i generisati sekvencu vrednosti.</s><s>Međutim, umesto da se pravi niz koji sadrži sve te elemente i i vraća sve njih, poziv generatora vraća jednu i samo jednu vrednost, što zahteva manje memorije i dopušta programeru da počne sa procesuiranjem prvih nekoliko vrednosti odmah.</s><s>Ukratko, generator liči na funkciju ali se ponaša kao iterator.</s>

<s>Generatori mogu biti implementirani u pogledu brže konstrukcije kontrole protoka, kao što su korutine ili nastavljanje prve-klase.</s><s>Generatori, takođe poznati kao polu-korutine, su specijalni slučaj (i slabiji od) korutina, u smislu da uvek daju povratnu kontrolu programeru (kada se vraća vrednost), umesto da odredi putanju korutini, videti komparacija korutina sa geratorima.</s>

<s>Upotreba 
Generatori se uglavnom izvršavaju unutar petlje.</s><s>Prvi put kada se generator izvrši u petlji, iteretorni objekat je kreiran da enkapsulira stanje generatora na njegovom početku, sa argumentima vezanih za odgovarajuće parametre.</s><s>Telo generatora je tada izvršavano u vidu iteratora sve do „yield“ naredbe; tada je vrednost obezbeđena operacijom „yield' korišćena kao vrednost prizvanog izraza.</s><s>Sleći put kada se pozove generator u naknadnoj iteraciji, izvršavanje tela generatora se nastavlja nakon operacije „yield“, sve dok ne dođe do sledeće „yield“ operacije.</s><s>U prilog operaciji „yield“, izvršavanje tela generatora se može završiti uz pomoć „finish“ naredbe, u kojoj se prekida ponavljanje u petlji generatora.</s><s>U mnogo komplikovanijim situacijama, generatori mogu biti korišćeni izvan petlje da bi se napravila iteracija, koja onda može biti upotrebljena na razne načine.</s>

<s>Pošto generatori izvršavaju njihove date vrednosti samo na poziv funkcije "yield“, korisni su za predstavljanje toka, kao sekvence koje bi bile skupe ili nemoguće za izvršavanje odjednom.</s><s>Ovo uključuje e.g. beskonačan broj sekvenci i tokova podataka.</s>

<s>Kada je željena procena poželjna (prvenstvetno kada je sekvenca konačna, jer se u suprotnom evaluacije nikad neće izvršiti), jedan može da se konvertuje u listu, ili da se koristi kao paralelni konstruktor koji kreira listu umesto generatora.</s><s>Na primer u Pajtonu generator g može biti označen listom l kao l = list(g), dok se u  F# ekspresija sekvenci seq { ... }  izvršava sporo (generator ili sekvenca) ali [ ... ] se izvršava efikasnije i poželjnije (lista).</s>

<s>U prisustvu generatora, konstrukcija petlje programa- kao što su for i while- može biti redukovana u jednu petlju...kraj konstrukcije petlje; sve obično korišćene konstrukcije petlji mogu biti stimulisane koristeći ispravno pogodan generator   .</s><s>Na primer, rangirana petlja kao što je for x = 1 to 10 može biti implementirana kao iteracija kroz generator, kao i u Pajtonu for x in xrange(10, 1).</s><s>Osim toga, break može biti implementirana tako što šalje naredbu  kraj  generatoru i posle toga koristeći continue u petlji.</s>

<s>Izgled 
Generatori su se prvo pojavili u CLU  (1975), gde je istaknuta odlika u vidu manipulacije stringa u programskom jeziku Icon (Ajkon) (1977) a sada je dostupna u Pajtonu, C#, Rubi, nadolazećoj verziji ECMASkript (Harmonija/ES6) i drugim programima.</s><s>U CLU i C#, generatori se nazivaju „iteratori“, a u programskom jeziku Rubi, "enumeratori".</s>

<s>Lisp 
Konačni Zajednički Lisp ne podržava prirodno generatore, još postoji varirajuća biblioteka implementacija, kao što su SERIJE dokumentovane u CLtL2 ili pajgenu (pygen).</s>

<s>CLU (CLU) 
Yield funkcija je korišćena da implementira iteratore preko korisničko-definisane abstrakcije podataka .string_chars = iter (s: string) yields (char);
  index: int := 1;
  limit: int := string$size (s);
  while index <= limit do
    yield (string$fetch(s, index));
    index := index + 1;
    end;
end string_chars;</s>

<s>for c: char in string_chars(s) do
   ...
end;</s>

<s>Ajkon (Icon) 
Svaka ekspresija (uključujući petlje) je generator.</s><s>Program ima mnogo ugrađenih generatora, čak i neke logičko semantičke implementacije koriste mehanizam generatora (Disjunkcija ili "ILI" je urađena tako).</s>

<s>Štampanje kvadrata od 0 do 20 se postiže koristeći ko-rutine, pišući:     local squares, j
   squares := create (seq(0) ^ 2)
   every j := |@squares do
      if j <= 20 then
         write(j)
      else
         breakMeđutim, uglavnom se željeni generatori implementiraju sa suspendovanom ključnom rečju sa funkcijama kao što je yield ključna reč u CLU.</s>

<s>C++ 
Moguće je uvesti generatore u C++ koristeći pre-procesorske makroe.</s><s>Rezultirajući kod može imati aspekte različite od prirode C++, ali sintaksa generatora može biti vrlo neopterećena.</s><s>Veoma dobar primer se može naći na.</s><s>Komplet preprocesorskih makroa definisanih u ovom kodu dozvoljava generatore definisanih sintaksama kao u sledećem primeru :$generator(descent)
{
   // mesto za sve vrednosti korišćene u generatoru
   int i; // naš brojač</s>

<s>// mesto konstrukcije našeg generatora, e.g. 
   // vrednost (int minv, int maxv) {...}
   
   // od $(emit)emitovanja do $(stop)stop je telo našeg generatora:
    
   $emit(int) // će emitovati celobrojne vrednosti.</s><s>Poćetak tela generatora:
      for (i = 10; i > 0; --i)
         $yield(i); // poznato kao yield u Pajtonu,
                    // vraća sledeći broj u [1..10], preokrenut.
   $stop; // stop, kraj sekvence.</s><s>Kraj tela generatora.
};Ovo može biti izvršeno koristeći:int main(int argc, char* argv[])
{
  descent gen;
  for(int n; gen(n);) // "sledeći" poziv generatora
    printf("next number is %d\n", n);
  return 0;
}Štaviše, C++11 dozvoljava svakoj petlji da bude primenjena u bilo kojoj klasi koja podržava begin i end funkcije.</s><s>Onda je moguće napisati generator kao klase uz pomoć obe merne metode (begin and end) i iterativne metode (operator!=, operator++ and operator*) u istoj klasi.</s><s>Na primer, moguće je napisati sledeći proram:#uključujući <iostream>
int main()
{
    for (int i: range(10))
    {
        std::cout << i << std::endl;
    }
    return 0;
}Osnovni domet implementacije bi trebalo da izgleda ovako:class range
{
private:
    int last;
    int iter;</s>

<s>public:
    range(int end):
        last(end),
        iter(0)
    {}</s>

<s>// Merne funkcije
    const range& begin() const { return *this; }
    const range& end() const { return *this; }</s>

<s>// Funkcije iteratora
    bool operator!=(const range&) const { return iter < last; }
    void operator++() { ++iter; }
    int operator*() const { return iter; }
};</s>

<s>Perl (Perl) 
Perl nema prirodno ugrađene generatore, ali podržavanje je sponzorisano od strane Koro Generatora modul koji koristi Koro ko-rutine okvir.</s><s>Primer korišćenja. koristiti striktno;
koristiti upozorenja;
# Aktivirati generator { BLOCK } i ''yield''
koristiti Koro::Generator;
# Niz upućuje na izvršavanje preko mojih $znakova = ['A'...</s><s>'Z'];
# Novi generator se može nazvati ''coderef''.
my $letters = generator {
    my $i = 0;
    for my $letter (@$chars) {
        # uzmi sledeće slovo od $chars
        yield $letter;
    }
};
# Pozovi generator 15 puta.
print $letters->(), "\n" for (0..15);</s>

<s>Tcl (Tcl) 
U Tcl-y 8.6, mehanizam generatora počiva na imenovanju korutina.proc generator {body} {
    coroutine gen[incr ::disambiguator] apply {{script} {
        # produkuje rezultat [generatora], ime generatora
        yield [info corutine]
        # Uradi stvaranje
        eval $script
        # Završiti petlju poziva koristeći 'break' izuzetak.
        return -code break
    }} $body
}
# Koristiti jednostavnu 'for' petlju za stvaranje 
set count[generator {
    for {set i 10} {$i <= 20} {incr i} {
        yield $i
    }
}]
# Izvlači vrednosti iz generatora dok se ne iscrpe
while 1 {
    puts [$count]
}</s>

<s>Haskel (Haskell) 
U Haskelu, sa sporim određivanjem vrdnosti modelom, sve je generator- svaki datum kreiran sa ne-strogom konstrukcijom podataka je generisan na zahtev.</s><s>Na primer,countfrom n = n : countfrom (n+1)</s>

<s>-- Example use: printing out the integers from 10 to 20.
test1 = mapM_ print $ takeWhile (<= 20) $ countfrom 10</s>

<s>primes = 2 : 3 : nextprime 5 where
  nextprime n | b = n : nextprime (n+2)
              | otherwise = nextprime (n+2)
    where b = all ((/= 0).(rem n)) $ takeWhile ((<= n).(^2)) $ tail primesgde je (:) ne-stroga lista konstruktora, protiv, i $ je samo "pozovi-sa" operator, korišćen za parentizaciju.</s><s>Ovo koristi standarni adaptor funkcija,takeWhile p [] = []
takeWhile p (x:xs) | p x = x : takeWhile p xs
                   | otherwise = []čije se ponovno pronađene vrednosti slažu sa iskazom, i prestaju sa traženjem novih vrednosti čim se izvrši jedna neodgovarajuća vrednost.</s><s>Pristup zajedničkom skladištu je korišćeno kao univerzalan posrednik u Haskelu.</s><s>Lista shvatanja može biti besplatno korišćena:test2 = mapM_ print $ takeWhile (<= 20) [x*x | x <- countfrom 10]
test3 = mapM_ print [x*x | x <- takeWhile (<= 20) $ countfrom 10]</s>

<s>Raket (Racket) 
Raket omogućava nekoliko pratećih objekata za generatore.</s><s>Prvo, njena for-petlja ima formu rada sa sekvencama, koja je vrsta proizvođača:(for ([i (in-range 10 20)])
  (printf "i = ~s\n" i))i ove sekvence su takođe vrednosti prve-klase:(define 10-to-20 (in-range 10 20))
(for ([i 10-to-20])
  (printf "i = ~s\n" i))Neke sekvence su imperativno implementirane (sa skrivenim vrednostima varijabli) a neke su implementirane kao (verovatno beskonačne) lenje liste.</s><s>Takođe, nova struktura definicije može imati moć koja određuje kako se mogu koristiti kao sekvence.</s>

<s>Ali više direktno, Raket ima laboratoriju generatora za tradicionalnu specifikaciju generatora.</s><s>Na primer,#''lang'' raket
(require racket/generator)
(define (ints-from from)
  (generator ()
    (for ([i (in-naturals from)]) ; infinite sequence of integers from 0
      (yield i))))
(define g (ints-from 10))
(list (g) (g) (g)) ; -> '(10 11 12)Primetiti da Raketovo jezgro implementira snažnu ponavljajuću karakteristiku, obezbeđujući opšta ponavljanja koja su kompatibilna ali takođe i ograničena.</s><s>Koristeći ovo, biblioteka generatora je implementirana u Raketu.</s>

<s>PHP (PHP) 
Zajednica PHP-a je implementirala generatore u PHP 5.5.</s><s>Detalji se mogu pornaći na RFC o generatorima.function fibonacci() {
    $last = 0;
    $current = 1;
    yield 1;
    while (true) {
        $current = $last + $current;
        $last = $current - $last;
        yield $current;
    }
}</s>

<s>foreach (fibonacci() as $number) {
    echo $number, "\n";
}</s>

<s>Rubi (Ruby) 
Rubi podržava generatore (počevši od verzije 1.9) u formi ugrađene Enumeratorske klase.# Generator iz Enumeratorskog objekta
chars = Enumerator.new(['A', 'B', 'C', 'Z'])</s>

<s>4.times { puts chars.next }
# Generator iz bloka
count = Enumerator.new do |yielder
| i = 0
  loop { yielder.yield i += 1 }
end</s>

<s>100.times { puts count.next }</s>

<s>Java  
Java je imala standardni pristup za implementiranje iteratora još od ranih svojih dana, i od Jave 5, foreach konstrukcija čini to lakšim za ponavljanje preko objekata koje omogućava java.lang.</s><s>Iterable pristup. ( Okvir java kolekcije i ostale okvirne kolekcije, proizvode iteratore za sve kolekcije.)</s>

<s>Međutim, Java nema ugrađene generatore.</s><s>Ovo znači da je kreiranje iteratora češće mnogo komplikovanije nego u programima koji imaju ugrađene generatore, pogotovo kada je stvaranje kompleksno.</s><s>Zbog toga što se sve vrednosti moraju snimiti i sačuvati svaki put kada se pozove stvar iz iteratora, nije moguće sačuvati vrednosti u lokalnim varijablama ili koristiti ugrađenu ponavljačku rutinu, kao kada su generatori dostupni; umesto toga, sve ovo mora biti manalno simulirano, koristeći polja da čuva lokalnu vrednost i broj ponavljanja.</s>

<s>Čak i jednostavni iteratori izgrađeni na ovaj način imaju tedenciju da budu značajno glomazniji od onih koji koriste generatori, sa mnogo opštenamenskih kodova.</s>

<s>Originalan primer se može napisati u Java 7 kao:// Iterator je implementiran kao anonimna klasa.</s><s>Ovo se koristi generički ali nije potrebno.
for (int i: new Iterable<Integer>() {
    @Override
    public Iterator<Integer> iterator() {
        return new Iterator<Integer>() {
            int counter = 1;</s>

<s>@Override
            public boolean hasNext() {
                return counter <= 100;
            }</s>

<s>@Override
            public Integer next() {
                return counter++;
            }</s>

<s>@Override
            public void remove() {
                throw new UnsupportedOperationException();
            }
        };
    }
}) {
    System.out.println(i);
}Beskonačna Fibonačijeva sekvenca se takođe može mapisati kao iterator u Java 7:Iterable<Integer> fibo = new Iterable<Integer>() {
    @Override
    public Iterator<Integer> iterator() {
        return new Iterator<Integer>() {
            int a = 1, b = 1;
            int total;</s>

<s>@Override
            public boolean hasNext() {
                return true;
            }</s>

<s>@Override
            public Integer next() {
                total = a + b;
                a = b;
                b = total;
                return total;
            }</s>

<s>@Override
            public void remove() {
                throw new UnsupportedOperationException();
            }
        };
    }
};
// ovo se zatim može koristiti kao...
for (int f: fibo) {
    System.out.println("next Fibonacci number is " + f);
    if (someCondition(f)) break;
}</s>

<s>Takođe, beskonačna Fibonačijeva sekvenca se može napisati i u Java 8 koristeći tok pristupa:Stream.generate(new Supplier<Integer>() {
    int a = 1, b = 2;</s>

<s>public Integer get() {
        int temp = a;
        a = b;
        b = a + temp;
        return temp;
    }
}).forEach(System.out::print);Ili kao iterator iz Java 8 super-pristupa OsnovnogToka toka pristupa.public Iterable<Integer> fibonacci(int limit){
    return ()->{
        return Stream.generate(new Supplier<Integer>() {
            int a = 1, b = 2;</s>

<s>public Integer get() {
                int temp = a;
                a = b;
                b = a + temp;
                return temp;
            }
        }).limit(limit).iterator();
    }
}</s>

<s>// ovo se zatim može koristiti kao...
for (int f: fibonacci(10)) {
    System.out.println(f);
}</s>

<s>C# 
Primer C# 2.0 generatora ( yield je dostušam od C# verzije 2.0):
Oba ova primera se koriste generički, ali ne moraju. // Metoda koja uzima merni ulaz (verovatno niz)
// i vraća sve parne brojeve.
public static IEnumerable<int> GetEven(IEnumerable<int> numbers) {
    foreach (int i in numbers) {
        if ((i % 2) == 0) {
            yield return i;
        }
    }
}Moguće je koristiti više puta yield return funkciju i one se nalaze u sekvenci svake iteracije:public class CityCollection : IEnumerable<string> {
    public IEnumerator<string> GetEnumerator() {
        yield return "New York";
        yield return "Paris";
        yield return "London";
    }
}</s>

<s>HL(XL) 
U HL-u, iteratori su osnova "for" petlje:import IO = XL.</s><s>UI.</s><s>CONSOLE</s>

<s>iterator IntegerIterator (var out Counter : integer; Low, High : integer) written Counter in Low..</s><s>High is
    Counter := Low
    while Counter <= High loop
        yield
        Counter += 1</s>

<s>// Primetiti da I ne treba da bude deklarisano, zbog deklarisanog ''var out'' u iteratoru
// Implicitna deklaracija I kao celobrojna vrednost je napravljena ovde
for I in 1..5 loop
    IO.</s><s>WriteLn "I=", I</s>

<s>F# 
F# sadrži generatore preko ekspresija sekvence, od verzije1.9.1.</s><s>Ovo može definisati sekvencu (sporu, sekvencijalnog pristupa) preko seq { ... }, liste (brza, sekvencijalnog pristupa) preko [ ... ] ili niza (brz, indeksnog pristupa) preko [| ... |] koja sadrži kod koji generiše vrednosti.</s><s>Na primer,seq { for b in 0 ..</s><s>25 do
          if b < 15 then
              yield b * b }forma sekvence kvadrata brojeva od 0 do 14, ispitivanjem brojeva u rasponu od 0. do 25.</s>

<s>Pajton (Python) 
Generatori su dodati u Pajton u verziji 2.2.</s><s>Primer generatora:def countfrom(n):
    while True:
        yield n
        n += 1
# Primer: štampa celobrojne vrednosti od 10 do 20
# Primetiti da se ova iteracija prestaje sa izvršavanjem normalno, uprkos
# countfrom() je napisana kao beskonačna petlja.</s>

<s>for i in countfrom(10):
    if i <= 20:
        print(i)
    else:
        break
# Još jedan generator, koji proizvodi proste bojeve neograničeno, tj. koliko je nama potrebno.</s>

<s>def primes():
    yield 2
    n = 3
    p = []
    while True:
        # Ovo radi u Pajtonovim verzijama 2.5+ 
        if not any(n % f == 0 for f in 
                     itertools.takewhile(lambda f: f*f <= n, p)): 
            yield n
            p.append(n)
        n += 2U Pajtonu, generator može biti misao iteratora koji sadrži nepromenljiv (zaleđen) okvir skladišta  .</s><s>Kad god je iteratorova next() metoda pozvana, Pajton nastavlja nepromenljiv okvir, koji se izvršava normalno sve dok ne stigne do yield funkcije.</s><s>Generatorov okvir je zaleđen ponovo, i pozvana vrednost je vraćena pozivaocu (korisniku).</s>

<s>PEP (PEP) 380 (ubačen u Pajton 3.3) dodaje yield from ekspresiju, koja dozvoljava generatoru da proverava deo njegovih operacia za drugi generator .</s>

<s>Ekspresije Generatora 
Pajton ima modeliranu sintaksu po uzoru na listu spoznaja, koja se naziva ekspresija generatora i koja pomaže u kreiranju generatora.</s><s>Sledeći primer pokazuje korišćenje ekspresije generatora da se izračuna kvadrat iz brojača (funkcije generatora):squares = ( n*n for n in countfrom(2) )</s>

<s>for j in squares:
    if j <= 20:
        print(j)
    else:
        break</s>

<s>ECMASkript (ECMAScript) 
ECMASkript 6 (poznata kao Harmonija) će imati funkcije generatora.</s>

<s>Beskonačna Fibonačijeva sekvecna se može napisati koristeći funkciju generatora:// inspirisano od strane: http://wiki.ecmascript.org/doku.php?id=harmony:generators
function* fibonacci() {
    let [prev, curr] = [0, 1];
    while (true) {
        yield curr;
        [prev, curr] = [curr, prev + curr];
    }
}</s>

<s>var gen = fibonacci();
console.log(gen.next().value); // 1
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
console.log(gen.next().value); // 3
console.log(gen.next().value); // 5
console.log(gen.next().value); // 8</s>

<s>Vidi još 
 Lista želja za ostale konstrukcije koje sadrže sekvence vrednosti
 Iterator za koncept stvaranja jednog elementa liste u vremenu
 Iterejtee za alternativu
 Spora dodela vrednosti za proizvodnju vrednosti kada su potrebne
 Ko-rekurzija za potencijalno beskonačnu vrednost uz pomoć rekurzije umesto "yield"
 Korutine za još veću generalizovaciju od sabrutine
 Nastavljanje za generalizaciju kontrole protoka</s>

<s>Reference</s>

<s>Literatura 
 Stefan Murer, Stiv Omohundro, Dejvid Stotumaer i Klemens Siperski: abstrakcija iteracije u Sateru.</s><s>ACM Transakcije na Programske jezike i Sisteme, 18(1):1-15 (1996)</s>

<s>Programske konstrukcije</s>

