Estoy desconcertado por generateSequence en Kotlin. Parece que estoy leyendo el manual todo mal:
Esta es la firma de la función (para generateSequence Secuencia con semilla):
fun <T : Any> generateSequence( seed: T?, nextFunction: (T) -> T? ): Sequence<T> Entonces, la Sequence debe ser del mismo tipo que la semilla y también el siguiente valor debe ir a la próxima generación de iteraciones ...
Pero el ejemplo en el hombre es:
fun fibonacci(): Sequence<Int> { return generateSequence(Pair(0, 1), { Pair(it.second, it.first + it.second) }).map { it.first } } println(fibonacci().take(10).toList()) // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34] Entonces parecería que el tipo de Sequence es Int , la semilla es Pair<Int, Int> .
La función generadora mapea Pair<Int, Int> TO Int . ¿Cómo se construye el siguiente valor enviado al generador donde se construye el siguiente Pair<Int, Int> (la salida del generador es Int ...)?
¿Y cómo demonios sabe la función cuándo detenerse? El generador nunca devuelve null .
Entonces parecería que el tipo de Secuencia es Int, la semilla es Par.
La función fibonacci() dada usa generateSequence() para generar una secuencia de Pair y luego usa la función map para convertir esa secuencia en una secuencia de Int .
val pairs = generateSequence(Pair(0, 1), { Pair(it.second, it.first + it.second) }) // (0,1), (1,1), (1,2), (2,3), (3,5), (5,8) ... val ints = pairs.map { it.first } // 0, 1, 1, 2, 3, 5Si le ayuda a pensar en ello, puede imaginar que la primera secuencia "completa" se genera antes de que los pares se conviertan en números enteros.
¿Y cómo demonios sabe la función cuándo detenerse?
no lo hace Pero el ejemplo usa la función take() para truncar la secuencia a los primeros 10 elementos y luego los imprime en lugar de imprimir una secuencia infinita.
La secuencia es lazy ; solo genera valores (llamando a la función generadora dada) cuando es necesario. Entonces, cuando generateSequence() regresa, aún no ha generado nada, solo creó una secuencia que puede hacerlo. De manera similar, cuando se aplica a una secuencia, la llamada map() no asigna inmediatamente ningún valor, solo devuelve una secuencia modificada que lo hará si/cuando se genera algún valor. Solo cuando se llama take() la secuencia generará (y asignará) algunos valores; y debido a que take() se detiene después de 10 elementos, no generará más que eso.