2017-05-27 60 views
0

這將是一個科特林慣用替代以下蟒蛇協同程序片段:科特林替代Python的協程的產量和發送

def generator(): 
    c = 1 
    while True: 
    op = yield c 
    if op == 'inc': 
     c += 1 
    elif op == 'mult': 
     c *= 2 

# main 
g = generator() 
a = g.send(None) # start 
b = g.send('inc') 
c = g.send('mult') 
d = g.send('inc') 

print([a, b, c, d]) # 1, 2, 4, 5 

所以我需要從協程得到的值(?通過一個通道),但也送這些值返回到協程。我需要兩個頻道嗎?

+1

您嘗試了哪些解決方案?你應該指出這是一個嘗試的解決方案,或者不能正常工作。否則,你會說「請爲我寫代碼」,而不是「應該工作的代碼不是」 –

+0

您將op設置爲1,所以它不會滿足您遞增或遞增的條件。 – alex

回答

2

在Python和ES6中出現的那種雙向生成器在Kotlin中並不真正習慣,因爲Kotlin是一種靜態類型語言,因此雙向生成器使用起來相當笨拙。只要看看上面代碼中的g.send(None)就可以理解爲什麼會這樣。因此,Kotlin標準庫中不提供雙向生成器的實現,也不提供支持庫。

但是,Kotlin語言中的協程支持是足夠通用的,並且如果需要,可以實現雙向生成器,以像在Python和ES6中一樣運行。相應的實現可用here,只需要幾行代碼。

通過上述實施雙向發電機,Python代碼可以直接翻譯成科特林行由行:

fun generator() = generate<Int, String> { 
    var c = 1 
    while (true) { 
     val op = yield(c) 
     when (op) { 
      "inc" -> c += 1 
      "mult" -> c *= 2 
     } 
    } 
} 

fun main(args: Array<String>) { 
    val g = generator() 
    val a = g.next("") // start 
    val b = g.next("inc") 
    val c = g.next("mult") 
    val d = g.next("inc") 
    println("$a $b $c $d") // 1, 2, 4, 5 
} 

此代碼的工作只是以及它的Python版本,但它是由於多種原因而不是習慣用語。首先,Kotlin中的協程支持允許定義任意暫停函數,從而可以以類型安全的方式表達類似的行爲,而不訴諸任意的開始標記,也不使用字符串來表示操作。您可以直接定義一個具有incmult作爲其第一類暫停操作的對象,或者至少可以更改實現,以便不需要虛擬開始調用。歡迎您研究coroutines design document,它解釋了Kotlin提供的所有低級原語,並且有許多示例可幫助您入門。