我正在浏览Kotlin的coroutines文档,并且在此示例之前一直很顺利。我很难理解它在找到素数时的计算方式,特别是filter
函数的返回值是如何返回并分配给cur
的,以及仍然使用numbersFrom
方法生成数字。
我已经添加了调试语句来尝试跟踪正在运行的各种协同程序,但是当它启动新的协同程序并从其他程序接收数字时,我仍然失去了逻辑流程。
代码:
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
答案 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算法的逻辑。
查看animation:filter(2)
以红色显示。
filter(3)
是绿色的,
filter(5)
是蓝色等等。