2016-12-02 5 views
0

Ich habe Mühe, die Idee von implicit in Scala auf Akka Streams anzuwenden.Akka Streams: Warum muss der GraphDSL.Builder als implizit markiert werden?

Nach http://docs.scala-lang.org/overviews/core/implicit-classes.html, das Grundkonzept einer implicit Klasse in Scala ist, dass für 5 times prinln("foo") ein Objekt von IntWithTimes erstellt wird, die Methode zu machen times implizit verfügbar durch Helpers._ importieren.

object Helpers { 
    implicit class IntWithTimes(x: Int) { 
    def times[A](f: => A): Unit = { 
     def loop(current: Int): Unit = 
     if(current > 0) { 
      f 
      loop(current - 1) 
     } 
     loop(x) 
    } 
    } 
} 

wir folgendes Beispiel:

val g = RunnableGraph.fromGraph(GraphDSL.create() { 
    implicit builder: GraphDSL.Builder[Unit] => 
    import GraphDSL.Implicits._ 

    val in = Source(1 to 100) 
    val flow = Flow[Int].map(_ + 1) 
    val out = Sink.foreach(println) 

    in ~> flow ~> out 
    ClosedShape 
}) 

g.run() 

Offensichtlich ist neu in Scala und Akka, meine unbefriedigende Theorie ist so weit, dass create() von GraphDSL mit einem RunnableGraph schafft die Builder hinein, indem.

Warum muss es als implicit markiert werden? Wenn sie weg sind, können die Operatoren ~> nicht mehr aufgelöst werden - obwohl GraphDSL.Implicits._ explizit importiert wird.

Antwort

2

implicit hat mehrere Anwendungsfälle in Scala, eine davon sind die impliziten Klassen, die Sie erwähnen. Es gibt jedoch auch implicit parameters und implicit conversions. Ich empfehle, diese zu lesen, es ist ein bisschen viel für den Umfang dieser Antwort und würde unnötig Informationen duplizieren. Beachten Sie jedoch, dass implizite Klassen meistens syntactic sugar for a class with an implicit conversion sind, also funktionieren sie gleich.

Wenn nicht, können die ~> -Operatoren nicht mehr aufgelöst werden - obwohl GraphDSL.Implicits._ explizit importiert wird.

Dies importiert die impliziten Konvertierungen zu FlowOps wo ~> tatsächlich definiert ist. An diesem Punkt kennt Scala die Konvertierung. Um dies jedoch tatsächlich auszuführen, benötigt es einen impliziten Parameterb : Builder[_]. Werfen Sie einen Blick auf die Umwandlung Definition in Implicits:

implicit def fanOut2flow[I, O](j: UniformFanOutShape[I, O])(implicit b: Builder[_]): PortOps[O] 

Jetzt können Sie einen beliebigen Builder[_] als implizite markieren und Scala wird dieser Parameter in automatisch für Sie ausfüllen, wenn es fehlt. Wenn Sie das Schlüsselwort implicit aus Ihrem Builder entfernen, bedeutet dies, dass kein impliziter Wert mehr verfügbar ist, um diesen Parameter zu füllen, was bedeutet, dass die Konvertierung nicht stattfinden kann und die Methode ~> nicht verfügbar ist.

Sie sind jedoch frei, die implizite Konvertierung manuell aufrufen und in der fehlenden Parameter selbst (Umgehen des gesamten impliziten Parameter Funktionalität) füllen, aber das würde aussehen sehr hässlich/verbose im Vergleich:

in ~> // .. and so on 
// would become 
fanOut2flow(in)(builder) ~> // .. and so on 
+0

Danke sehr viel zu dieser ausführlichen Erklärung! Ich habe nicht genug darauf geachtet, dass die implizite Konvertierung den Builder als (impliziten) Parameter benötigt. Danke, dass du das unterstrichen hast! – Toaditoad

Verwandte Themen