Geradores
No JavaScript um gerador é uma função que retorna uma lista de valores, só que
um por vez. Para conseguirmos o próximo valor, usamos a função next()
que
retorna um objeto com o atributo value
que é o próximo valor e o atributo
done
que indica se a gerador terminou. Além disso é necessário um asterisco *
na frente da função.
Quando um gerador atinge a palavra-chave yield
, ele pausa e retorna o valor
atual. Na próxima chamada, o gerador continua a partir do local onde parou.
Por exemplo se quisermos criar um gerador de números de 1 a 10, podemos fazer:
var contador = function* (n) {
var numero = 1;
while (numero <= n) {
yield numero;
numero++;
}
};
var gerador = contador(10);
while (true) {
var proximo = gerador.next();
// Verifica se a geração terminou
if (proximo.done) break;
console.log(proximo.value);
}
Um gerador não necessariamente precisa ter um fim, podemos criar um gerador que vai gerar números infinitamente:
var fibonacci = function* (n) {
var a = 1,
b = 1;
while (true) {
yield a;
var temp = a;
a = b;
b = temp + b;
}
};
var gerador = fibonacci();
while (true) {
var proximo = gerador.next();
// Verifica se a geração terminou (nunca vai acontecer)
if (proximo.done) break;
console.log(proximo.value);
}
// Resultado: 1, 1, 2, 3, 5, 8, 13, ... (infinitamente)
Ainda existe a sintaxe yield*
que serve para chamar um gerador de outro
gerador. Por exemplo:
var contador1 = function* (n) {
var numero = 1;
while (numero <= n) {
yield numero;
numero++;
}
};
var contador2 = function* (n) {
var numero = 1;
while (numero <= n) {
yield* contador1(numero);
numero++;
}
};
var gerador = contador2(4);
while (true) {
var proximo = gerador.next();
// Verifica se a geração terminou
if (proximo.done) break;
console.log(proximo.value);
}
// Resultado: 1, 1, 2, 1, 2, 3, 1, 2, 3, 4