2017-05-27 4 views
0

Was für eine Kotlin idiomatische Alternative zu folgendem Python Koroutine Schnipsel wäre:Kotlin Alternative zu Pythons Koroutine Ausbeute und senden

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 

Also muss ich Werte aus dem Koroutine (? Über einen Kanal), sondern auch senden die Werte zurück in die Coroutine. Brauche ich zwei Kanäle dafür?

+1

Welche Lösungen haben Sie ausprobiert? Sie sollten das als eine versuchte Lösung herausstellen, die funktioniert oder nicht funktioniert. Sonst sagst du "Bitte schreibe meinen Code für mich" anstelle von "dieser Code, der funktionieren soll, nicht" –

+0

Du setzt op auf c, was 1 ist, also wird es niemals deine Bedingungen für Inkrementieren oder Multiplizieren erfüllen. – alex

Antwort

2

Zwei-Wege-Generatoren, wie sie in Python und in ES6 vorkommen, sind in Kotlin nicht wirklich idiomatisch, da Kotlin eine statisch typisierte Sprache ist und daher Zwei-Wege-Generatoren ziemlich unbeholfen zu verwenden sind. Werfen Sie einen Blick auf die g.send(None) im obigen Code, um zu verstehen, warum es so ist. Daher ist die Implementierung von Zweiwegegeneratoren weder in der Kotlin-Standardbibliothek noch in unterstützenden Bibliotheken vorgesehen.

Allerdings ist Koroutinen-Unterstützung in Kotlin-Sprache generisch genug und Zwei-Wege-Generatoren können implementiert werden, falls erforderlich, um sich wie in Python und ES6 zu verhalten. Die entsprechende Implementierung ist verfügbar here und dauert nur ein paar Dutzend Zeilen Code.

Mit der obigen Implementierung von Zwei-Wege-Generator können Sie Ihre Python-Code direkt in übersetzt werden Kotlin line-by-line:

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 
} 

Dieser Code funktioniert genauso gut wie seine Python-Version, aber es ist aus vielen Gründen nicht idiomatisch. Zum einen ermöglicht die Koroutinen-Unterstützung in Kotlin die Definition von willkürlichen Aussetzungsfunktionen und ermöglicht somit, ein ähnliches Verhalten typsicher auszudrücken, ohne auf eine willkürliche Startmarkierung zurückzugreifen, oder Zeichenfolgen zu verwenden, um Operationen zu bezeichnen. Sie können einfach ein Objekt definieren, das inc und mult als seine ersten aussetzenden Operationen hat, oder zumindest die Implementierung ändern, so dass ein Dummy-Startaufruf nicht benötigt wird. Sie sind herzlich eingeladen, coroutines design document zu studieren, in dem alle Low-Level-Primitive erklärt werden, die Kotlin zur Verfügung stellt, und eine Reihe von Beispielen, die Ihnen den Einstieg erleichtern.