Kotlin Coroutines文档中的素数示例如何工作?

时间:2017-06-06 16:19:59

标签: kotlin

我正在浏览Kotlin的coroutines文档,并且在此示例之前一直很顺利。我很难理解它在找到素数时的计算方式,特别是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

2 个答案:

答案 0 :(得分:3)

示例的目的是实现Sieve of Eratosthenes。换句话说,通过过滤掉由于它们的可分性而不能成为素数的数字来查找素数。剩下的都是素数。

让我们来看看我们拥有的东西。我现在要忽略所有context变量,它只是让事情更容易讨论。

首先,我们有一个名为numbersFrom的函数,它只是一个从2开始的无限整数序列(在本例中)。

我们还有一个名为filter的函数,它接收一个通道,以及一个可能是素数的数字。查看返回类型,我们可以看到此函数返回一个新的生成器。为了产生结果(在这种情况下为Int),可以调用send函数。查看函数的正文,filter将接受通道上的数字(通过send)和 REJECT 可以被素数整除的任何内容(无所事事) 。

例如,如果频道产生4且素数为2,则拒绝该频道。另一方面,如果通道产生5并且素数为2,则它将send该数字。现在显而易见的是filter做了它的名字所说的内容 - 读取输入,找到喜欢的输入,将它们发送到输出。

现在让我们来看看主要功能。首先,我们创建一个从2开始的数字流(这是巧合,第一个素数!)并将其分配给cur。到目前为止,非常好。

接下来,我们开始循环。我将10减少到3以使事情更容易理解,但基本上这个数字意味着主要方法将计算多少素数。如果您想要前100个素数,请将其设置为100.

在循环中,我们通过调用receive()上的cur从号码列表中取出第一个号码。这是一个暂停功能。正如我上面提到的,它将获得2作为其第一个prime值。

现在这里是有趣的部分。我们接受2,并将其用作filter调用的基础,以及当前为cur的流Int,并将其重新分配给cur cur。那是什么意思呢? cur现在代表一个Ints流,过滤后不能被2整除!

在下一个循环中,我们从filter(2)频道中取出第一个数字,它是一个3.下一个素数。为什么是3?因为filter允许它通过(3%2!= 0)。这是有趣的部分。现在我们采用cur(一个不能被2整除的数字的过滤列表)并将其传递给cur函数以及3(我们最近的素数)。现在numbers -> filter(2) -> filter(3) 表示不能被2或3整除的数字流。看看这是怎么回事?

基本上在这一点上我们有这个:

filter(3, filter(2, numbers))

或者,阅读另一个(不那么精确的wrt协程,但更容易想象):

cur

任何使其成为 function capTo1or0 (Tensor3d) tensor_width=Tensor3d:size()[2] tensor_height=Tensor3d:size()[3] tensor_depth=Tensor3d:size()[1] for i=1,tensor_width,1 do for j=1,tensor_height,1 do for k=1,tensor_depth,1 do if(Tensor3d[k][i][j])>1 then Tensor3d[k][i][j]=1 end if(Tensor3d[k][i][j]<0.0) then Tensor3d[k][i][j]=0.0 end end end end return Tensor3d end 头部的数字都是素数,因为它通过了所有过滤器。

感谢您提出这个问题! “Go learn Kotlin Coroutines”已经在我的研究名单上待了几个星期,我早上好好读了解它们并搞清楚了。

答案 1 :(得分:2)

确保您了解Sieve of Eratosthenes算法的逻辑。

查看animationfilter(2)以红色显示。 filter(3)是绿色的, filter(5)是蓝色等等。

相关问题