2017-05-27 2 views
0

を送信:Pythonのコルーチン収量にKotlinの代替と次のpythonコルーチンスニペットにKotlin慣用代わるだろう何

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 

だから私は(チャネルを介して?)コルーチンから値を取得する必要がありますが、また送信値はコルーチンに戻ります。それには2つのチャンネルが必要ですか?

+1

どのような解決策を試しましたか?あなたはそれが試みられている解決策として働いているかどうかを指摘する必要があります。それ以外の場合は、「このコードは動作しません」の代わりに「自分のコードを書いてください」と言います。 –

+0

opをcに1に設定しているため、増分または乗算の条件を満たすことはありません。 – alex

答えて

2

Kotlinは静的型付けされた言語であるため、2ウェイジェネレータは使用するのが非常に面倒なので、PythonとES6に存在する種類の双方向ジェネレータは実際にはKotlinでは慣用的ではありません。上記のコードのg.send(None)を調べて、その理由を理解してください。したがって、双方向ジェネレータの実装は、Kotlin標準ライブラリやサポートライブラリでは提供されていません。

しかし、Kotlin言語でサポートされているコルーチンは十分に一般的であり、必要に応じてPythonとES6のように動作するように双方向ジェネレータを実装できます。対応する実装はhereで利用可能で、わずか数十行のコードが必要です。双方向の発電機の上記の実装では

は、あなたのPythonコードは、直接に変換することができKotlinライン・バイ・ライン:

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のバージョンだけでなくだけで動作します多くの理由から慣用ではありません。 1つは、Kotlinのコルーチンサポートが任意の中断関数の定義を可能にし、任意の開始マーカーに頼らず、操作を表すために文字列を使用することなく、同様の動作を型安全に表現できることです。 incmultを持つオブジェクトをファーストクラスの中断操作として直接定義するか、少なくともダミーの開始呼び出しが不要になるように実装を変更します。 coroutines design documentを勉強して、Kotlinが提供するすべての低レベルプリミティブについて説明しており、開始するためのいくつかの例があります。

関連する問題