Intereting Posts
Использовать NumberFormat.getCurrency в Kotlin Android Ошибка плагина Kotlin в студии Android Китгер 2 не распознает метод предоставления в Котлине. Java отлично работает Котлин в андроид-студии Ошибка сборки: ошибка: выполнение не выполнено для задачи: app: compileLightningLiteDebugKotlin '. > Ошибка компиляции Можно ли аннотировать конструктор классов в Котлине Невозможно использовать все параметры конфигурации с настраиваемой конфигурацией в градиенте с помощью kotlin-dsl Spring Boot не может запускать одиночный тест в IntelliJ Что является предпочтительным решением для Kotlin koan «Partition» и почему? java static final в kotlin: инициализатор Const 'val' должен быть постоянным значением AES-шифрование. Различия между PHP и Kotlin \ Java Kotlin: реализация LinkedList Метод подстановки Котлина Array / List iteration без дополнительных распределений объектов Как правильно показать прогресс асинхронных задач, используемых Google Room

Как работает пример простых чисел из документации Kotlin Coroutines?

Я просматриваю сопроводительную документацию для Kotlin и хорошо слежу до этого примера. Мне очень сложно понять, как он вычисляет, когда он находит простое число, и конкретно, как возврат из функции filter возвращаются и назначаются на cur , а также все еще производят числа из метода numbersFrom .

Я добавил операторы отладки, чтобы попытаться выполнить различные выполняемые сопрограммы, но я все еще теряюсь в логическом потоке, когда он запускает новые сопрограммы и получает числа от других.

https://github.com/Kotlin/kotlinx.coroutines/blob/master/coroutines-guide.md#prime-numbers-with-pipeline

Код:

 fun log(msg: String) = println("[${Thread.currentThread().name}] $msg") fun main(args: Array<String>) = runBlocking<Unit> { var cur = numbersFrom(context, 2) for (i in 1..10) { val prime = cur.receive() println(prime) cur = filter(context, cur, prime) } } fun numbersFrom(context: CoroutineContext, start: Int) = produce<Int>(context) { var x = start while (true) { log("NumbersFrom Send: ${x}") send(x++) } // infinite stream of integers from start } fun filter(context: CoroutineContext, numbers: ReceiveChannel<Int>, prime: Int) = produce<Int>(context) { for (x in numbers) { log("filter ${x}, prime ${prime}") if (x % prime != 0) { send(x) } } } 

Outout:

 [main @coroutine#2] NumbersFrom Send: 2 [main @coroutine#2] NumbersFrom Send: 3 2 [main @coroutine#3] filter 3, prime 2 [main @coroutine#2] NumbersFrom Send: 4 [main @coroutine#2] NumbersFrom Send: 5 3 [main @coroutine#3] filter 4, prime 2 [main @coroutine#3] filter 5, prime 2 [main @coroutine#4] filter 5, prime 3 [main @coroutine#2] NumbersFrom Send: 6 [main @coroutine#3] filter 6, prime 2 5 [main @coroutine#2] NumbersFrom Send: 7 [main @coroutine#2] NumbersFrom Send: 8 [main @coroutine#3] filter 7, prime 2 [main @coroutine#3] filter 8, prime 2 [main @coroutine#4] filter 7, prime 3 [main @coroutine#2] NumbersFrom Send: 9 [main @coroutine#2] NumbersFrom Send: 10 [main @coroutine#5] filter 7, prime 5 [main @coroutine#3] filter 9, prime 2 [main @coroutine#3] filter 10, prime 2 7 [main @coroutine#4] filter 9, prime 3 [main @coroutine#2] NumbersFrom Send: 11 [main @coroutine#2] NumbersFrom Send: 12 [main @coroutine#3] filter 11, prime 2 [main @coroutine#3] filter 12, prime 2 [main @coroutine#4] filter 11, prime 3 [main @coroutine#2] NumbersFrom Send: 13 [main @coroutine#2] NumbersFrom Send: 14 [main @coroutine#5] filter 11, prime 5 [main @coroutine#3] filter 13, prime 2 [main @coroutine#3] filter 14, prime 2 [main @coroutine#6] filter 11, prime 7 [main @coroutine#4] filter 13, prime 3 [main @coroutine#2] NumbersFrom Send: 15 [main @coroutine#2] NumbersFrom Send: 16 11 [main @coroutine#5] filter 13, prime 5 [main @coroutine#3] filter 15, prime 2 [main @coroutine#3] filter 16, prime 2 [main @coroutine#6] filter 13, prime 7 [main @coroutine#4] filter 15, prime 3 [main @coroutine#2] NumbersFrom Send: 17 [main @coroutine#2] NumbersFrom Send: 18 [main @coroutine#7] filter 13, prime 11 [main @coroutine#3] filter 17, prime 2 [main @coroutine#3] filter 18, prime 2 13 [main @coroutine#4] filter 17, prime 3 [main @coroutine#2] NumbersFrom Send: 19 [main @coroutine#2] NumbersFrom Send: 20 [main @coroutine#5] filter 17, prime 5 [main @coroutine#3] filter 19, prime 2 [main @coroutine#3] filter 20, prime 2 [main @coroutine#6] filter 17, prime 7 [main @coroutine#4] filter 19, prime 3 [main @coroutine#2] NumbersFrom Send: 21 [main @coroutine#2] NumbersFrom Send: 22 [main @coroutine#7] filter 17, prime 11 [main @coroutine#5] filter 19, prime 5 [main @coroutine#3] filter 21, prime 2 [main @coroutine#3] filter 22, prime 2 [main @coroutine#8] filter 17, prime 13 [main @coroutine#6] filter 19, prime 7 [main @coroutine#4] filter 21, prime 3 [main @coroutine#2] NumbersFrom Send: 23 [main @coroutine#2] NumbersFrom Send: 24 17 [main @coroutine#7] filter 19, prime 11 [main @coroutine#3] filter 23, prime 2 [main @coroutine#3] filter 24, prime 2 [main @coroutine#8] filter 19, prime 13 [main @coroutine#4] filter 23, prime 3 [main @coroutine#2] NumbersFrom Send: 25 [main @coroutine#2] NumbersFrom Send: 26 [main @coroutine#9] filter 19, prime 17 [main @coroutine#5] filter 23, prime 5 [main @coroutine#3] filter 25, prime 2 [main @coroutine#3] filter 26, prime 2 19 [main @coroutine#6] filter 23, prime 7 [main @coroutine#4] filter 25, prime 3 [main @coroutine#2] NumbersFrom Send: 27 [main @coroutine#2] NumbersFrom Send: 28 [main @coroutine#7] filter 23, prime 11 [main @coroutine#5] filter 25, prime 5 [main @coroutine#3] filter 27, prime 2 [main @coroutine#3] filter 28, prime 2 [main @coroutine#8] filter 23, prime 13 [main @coroutine#4] filter 27, prime 3 [main @coroutine#2] NumbersFrom Send: 29 [main @coroutine#2] NumbersFrom Send: 30 [main @coroutine#9] filter 23, prime 17 [main @coroutine#3] filter 29, prime 2 [main @coroutine#3] filter 30, prime 2 [main @coroutine#10] filter 23, prime 19 [main @coroutine#4] filter 29, prime 3 [main @coroutine#2] NumbersFrom Send: 31 [main @coroutine#2] NumbersFrom Send: 32 23 [main @coroutine#5] filter 29, prime 5 [main @coroutine#3] filter 31, prime 2 [main @coroutine#3] filter 32, prime 2 [main @coroutine#6] filter 29, prime 7 [main @coroutine#4] filter 31, prime 3 [main @coroutine#2] NumbersFrom Send: 33 [main @coroutine#2] NumbersFrom Send: 34 [main @coroutine#7] filter 29, prime 11 [main @coroutine#5] filter 31, prime 5 [main @coroutine#3] filter 33, prime 2 [main @coroutine#3] filter 34, prime 2 [main @coroutine#8] filter 29, prime 13 [main @coroutine#6] filter 31, prime 7 [main @coroutine#4] filter 33, prime 3 [main @coroutine#2] NumbersFrom Send: 35 [main @coroutine#2] NumbersFrom Send: 36 [main @coroutine#9] filter 29, prime 17 [main @coroutine#7] filter 31, prime 11 [main @coroutine#3] filter 35, prime 2 [main @coroutine#3] filter 36, prime 2 [main @coroutine#10] filter 29, prime 19 [main @coroutine#8] filter 31, prime 13 [main @coroutine#4] filter 35, prime 3 [main @coroutine#2] NumbersFrom Send: 37 [main @coroutine#2] NumbersFrom Send: 38 [main @coroutine#11] filter 29, prime 23 [main @coroutine#9] filter 31, prime 17 [main @coroutine#5] filter 35, prime 5 [main @coroutine#3] filter 37, prime 2 [main @coroutine#3] filter 38, prime 2 29 [main @coroutine#10] filter 31, prime 19 [main @coroutine#4] filter 37, prime 3 [main @coroutine#2] NumbersFrom Send: 39 

В качестве примера можно привести Сито Эратосфена . Другими словами, найти простые числа, отфильтровывая числа, которые не могут быть первичными из-за их делимости. Все остальное – простое.

Давайте посмотрим, что у нас есть. На данный момент я буду игнорировать все переменные context , это просто облегчает разговор.

Во-первых, мы имеем функцию под названием numbersFrom , которая представляет собой просто бесконечную последовательность целых чисел, начинающуюся с 2 (в данном случае).

У нас также есть функция, называемая filter , которая принимает канал, и число, которое предположительно является простым. Посмотрев на тип возврата, мы видим, что эта функция возвращает нового производителя. Для получения результатов ( Int s в этом случае) можно вызвать функцию send . Глядя на тело функции, filter будет принимать числа от канала (через send ) и ОТКЛЮЧИТЬ все, что равномерно делится на простое число (ничего не делая).

Например, если канал создает 4, а штрих равен 2, это отклоняется. С другой стороны, если канал создает 5, а штрих равен 2, он send это число вместе. Теперь должно стать очевидным, что filter делает то, что говорит его имя, – читайте входы, находите те, которые ему нравятся, отправляйте их вместе с его выходом.

Теперь давайте посмотрим на основную функцию. Сначала мы создаем поток чисел, начинающийся с 2 (какое совпадение, первое простое!) И присваиваем его cur . Все идет нормально.

Затем мы начинаем цикл. Я уменьшил 10 до 3, чтобы упростить понимание, но в основном это число означает, сколько простых чисел будет вычислять основной метод. Если вы хотите получить первые 100 простых чисел, установите значение 100.

В цикле мы берем первый номер из списка чисел, вызывая метод receive() на cur . Это приостанавливающая функция. И, как я уже упоминал выше, он получит 2 в качестве первого prime значения.

И вот теперь самое интересное. Мы берем это 2 и используем его в качестве основы для вызова filter , а также cur , который в настоящее время является потоком Int s, и переназначаем это на cur . Так что это значит? cur теперь представляет поток Ints, отфильтрованный, чтобы НЕ быть делимым на 2 !.

В следующем цикле мы берем первый номер с канала-канала, а это 3. Следующее число. Почему это 3? Потому что filter(2) позволил ему пройти (3% 2! = 0). Это интересная часть. Теперь мы берем cur (отфильтрованный список чисел, которые не делятся на 2) и передают его в функцию filter вместе с 3 (наше последнее простое). Теперь cur представляет поток чисел, не делящихся на 2 или 3. Посмотрите, куда это идет?

По существу в этот момент мы имеем следующее:

 numbers -> filter(2) -> filter(3) 

Или, прочитайте еще один (менее точные ответы, но проще для изображения):

 filter(3, filter(2, numbers)) 

Любое число, которое превращает его в начало cur является простым, поскольку оно проходит через все фильтры.

Спасибо, что задали этот вопрос! « Пойдите, изучите Kotlin Coroutines », был в моем списке исследований на пару недель, и я хорошо прочитал о них и понял это.

Убедитесь, что вы понимаете логику алгоритма Сита Эратосфена .

Посмотрите анимацию : filter(2) отображается красным цветом. filter(3) зеленый, filter(5) синий и т. д.