web-dev-qa-db-fra.com

Comprendre la fonction de rendement de Kotlin

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.

  • Qu'est-ce que cela signifie qu'il s'agit d'une fonction de suspension?
  • Dans quels scénarios cela peut-il être avantageux?
15
Ahmed

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.

15
Alexey Soshin

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

4
Eugene Petrenko