Generadores: las partes más importantes

La especificación del borrador ECMAScript 6 ya ha brindado muchas fuentes de alegría al desarrollador moderno de JavaScript. En una publicación anterior, explicamos algunas clases de colecciones nuevas y los bucles de iteración de for..of. En esta publicación, hablaremos sobre algo que se complementa con los bucles for..of: las funciones de generador.

Ya existe un host de material excelente en el que se explican los motivos y el modo de usar los generadores. En pocas palabras, los generadores son funciones especiales que crean iteradores, mientras que los iteradores son objetos que tienen un método next(), al que se puede llamar para obtener un valor. En una función de generador, la palabra clave yield proporciona el valor de next(). El uso de yield suspende la ejecución de la función del generador y conserva el estado hasta que se vuelva a llamar a next(), momento en el que el código comienza de nuevo y continúa hasta que yield establece otro valor (o hasta que finaliza la función del generador). Hay varios casos de uso canónicos para las funciones del generador, como usarlos para iterar sobre los números de la secuencia de Fibonacci.

Ahora que ya nos ocupamos de los aspectos básicos, profundicemos en una muestra de JavaScript que abarque algunas de las trampas (o " pequeños detalles") del trabajo con generadores. Hay una gran cantidad de comentarios en todo momento y puedes probar con la versión publicada del código antes de leerlo:

¿Cuáles son algunas de las conclusiones importantes del código?

Primero, la construcción de un generador genera un iterador único con su propio estado, y puedes pasar parámetros al constructor del generador que puede controlar el comportamiento.

En segundo lugar, puedes pasar un parámetro cuando llames al método next() de un iterador, y ese valor se asignará a lo que esté a la izquierda de la sentencia yield de la invocación del iterador anterior. Esta es una excelente manera de variar la salida del iterador; aquí, la usamos para controlar si la palabra generada está en mayúsculas o no. Si deseas influir en el primer valor producido, hazlo mediante un parámetro en el constructor del generador.

Por último, los generadores pueden producir iteradores finitos o infinitos. Si trabajas con un iterador infinito, asegúrate de tener algún tipo de condición terminal basada en el valor yielded; es muy fácil escribir bucles infinitos por accidente, en especial cuando se usa for..of para la iteración. Si trabajas con un iterador finito mediante llamadas a next(), la propiedad .done del objeto que se muestra indica si se completó la iteración.

Esperamos que este ejemplo, junto con los otros recursos disponibles en la Web, atraiga algo de entusiasmo y te ayude a pensar en cómo puedes usar los generadores en tu propio código. Las versiones de Firefox que comienzan con la versión 31 y de Chrome a partir de la versión 39 admiten generadores de forma nativa. El proyecto Regenerator es compatible con el generador para otros navegadores. También se puede usar Traceur.

Agradecemos a Erik Arvidsson por su ayuda para revisar este artículo.