Los generadores en Dart son una característica poderosa que permite crear secuencias de valores de manera eficiente y perezosa (lazy). En lugar de generar todos los valores de una vez y almacenarlos en la memoria, los generadores producen valores bajo demanda, lo que puede ser muy útil para trabajar con grandes conjuntos de datos o secuencias infinitas.

Conceptos Clave

  1. Generadores Síncronos: Utilizan la palabra clave sync* y producen valores de manera síncrona.
  2. Generadores Asíncronos: Utilizan la palabra clave async* y producen valores de manera asíncrona.
  3. Yield: La palabra clave yield se utiliza para producir un valor en un generador.

Generadores Síncronos

Los generadores síncronos son funciones que devuelven un Iterable. Utilizan la palabra clave sync* y yield para producir valores.

Ejemplo de Generador Síncrono

Iterable<int> contador(int max) sync* {
  for (int i = 0; i <= max; i++) {
    yield i;
  }
}

void main() {
  var numeros = contador(5);
  for (var numero in numeros) {
    print(numero);
  }
}

Explicación:

  • La función contador es un generador síncrono que produce números del 0 al max.
  • La palabra clave sync* indica que es un generador síncrono.
  • La palabra clave yield se utiliza para producir cada número en la secuencia.
  • En el main, se itera sobre los números generados y se imprimen.

Generadores Asíncronos

Los generadores asíncronos son funciones que devuelven un Stream. Utilizan la palabra clave async* y yield para producir valores de manera asíncrona.

Ejemplo de Generador Asíncrono

Stream<int> contadorAsincrono(int max) async* {
  for (int i = 0; i <= max; i++) {
    await Future.delayed(Duration(seconds: 1));
    yield i;
  }
}

void main() async {
  var numeros = contadorAsincrono(5);
  await for (var numero in numeros) {
    print(numero);
  }
}

Explicación:

  • La función contadorAsincrono es un generador asíncrono que produce números del 0 al max con un retraso de 1 segundo entre cada número.
  • La palabra clave async* indica que es un generador asíncrono.
  • La palabra clave yield se utiliza para producir cada número en la secuencia.
  • En el main, se itera sobre los números generados utilizando await for y se imprimen.

Ejercicios Prácticos

Ejercicio 1: Generador de Números Pares

Instrucciones: Crea un generador síncrono que produzca los primeros n números pares.

Solución:

Iterable<int> numerosPares(int n) sync* {
  for (int i = 0; i < n; i++) {
    yield i * 2;
  }
}

void main() {
  var pares = numerosPares(5);
  for (var numero in pares) {
    print(numero);
  }
}

Ejercicio 2: Generador de Secuencia Fibonacci Asíncrono

Instrucciones: Crea un generador asíncrono que produzca los primeros n números de la secuencia de Fibonacci con un retraso de 500ms entre cada número.

Solución:

Stream<int> fibonacci(int n) async* {
  int a = 0, b = 1;
  for (int i = 0; i < n; i++) {
    await Future.delayed(Duration(milliseconds: 500));
    yield a;
    int temp = a;
    a = b;
    b = temp + b;
  }
}

void main() async {
  var fib = fibonacci(5);
  await for (var numero in fib) {
    print(numero);
  }
}

Resumen

En esta sección, hemos aprendido sobre los generadores en Dart, tanto síncronos como asíncronos. Los generadores son útiles para producir secuencias de valores de manera eficiente y perezosa. Hemos visto ejemplos prácticos y ejercicios para reforzar los conceptos aprendidos. En la siguiente sección, exploraremos los Isolates y cómo pueden ser utilizados para realizar tareas en paralelo en Dart.

© Copyright 2024. Todos los derechos reservados