Je ne vois pas de définition très claire de la fonction yield
dans Kotlin.
L'exemple dans le lien ci-dessus ne mentionne pas grand-chose mais ce qui suit,
val sequence = sequence {
val start = 0
// yielding a single value
yield(start)
// yielding an iterable
yieldAll(1..5 step 2)
// yielding an infinite sequence
yieldAll(generateSequence(8) { it * 3 })
}
println(sequence.take(7).toList()) // [0, 1, 3, 5, 8, 24, 72]
Mais l'exemple ci-dessus ne souligne pas l'importance du rendement.
Vous pouvez penser à yield()
comme "retour, et la prochaine fois commencez là où vous vous êtes arrêté":
val sequence = sequence {
val start = 0
yield(start) // first return
yieldAll(1..5 step 2) // if called again, will start from here
yieldAll(generateSequence(8) { it * 3 }) // if called more that six times, start from here
}
Il crée une machine à états et d'autres choses, mais vous pouvez le traduire en Java comme ceci:
class Seq {
private AtomicInteger count = new AtomicInteger(0);
private int state = 0;
public int nextValue() {
if (count.get() == 0) {
return state;
}
else if (count.get() >= 1 && count.get() <= 5) {
state += 2;
return state;
}
else {
state *= 3;
return state;
}
}
}
Dans la classe Java Java, nous maintenons un état explicite en ayant deux variables: count
et state
. Combinaison de sequence
et yield
permettre à cet état d'être maintenu implicitement.
Prenons un exemple, où vous pouvez générer l'élément suivant de la séquence, mais vous ne voyez pas un moyen facile d'implémenter un itérateur Java.
fun fibonacci() = sequence {
var a_0 = 1
var a_1 = 1
// this sequence is infinite
while(true) {
val a_n = a_0 + a_1
a_0 = a_1
a_1 = a_n
//this is a suspend function call
yield(a_0)
}
}
L'exemple utilise la fonction yield
pour renvoyer l'élément suivant de la séquence. La fonction est un exemple de fonction suspend
dans Kotlin. L'appel à la fonction suspend l'exécution de sequence{..}
block, donc la pile d'appels est libre.
Disons que nous faisons ce qui suit
fibonacci().take(10).forEach{
println(it)
}
Chaque itération de la boucle forEach
reprendra le sequence{..}
bloquer à partir de l'appel de fonction yield
précédent et le laisser s'exécuter jusqu'à l'appel de fonction yield
suivant. Le flux d'exécution mélangera les itérations de boucle forEach
avec sequence{..}
bloquer l'évaluation. Vous pouvez essayer d'écrire la même chose que Java Iterator
pour ressentir ce que fait le compilateur Kotlin dans les coulisses.
suspend
les fonctions de Kotlin se font de façon minimaliste côté langage et côté bibliothèque standard, le reste peut être implémenté dans les bibliothèques. Je recommande de vérifier le kotlinx.coroutines
bibliothèque pour plus d'informations, d'exemples et de documentation https://github.com/Kotlin/kotlinx.coroutines