Akka Streams:为什么必须将GraphDSL.Builder标记为隐式?

时间:2016-12-02 11:24:54

标签: scala akka implicit akka-stream

我很难将Scala中implicit的想法应用到Akka Streams。

根据http://docs.scala-lang.org/overviews/core/implicit-classes.html,Scala中implicit类的基本概念是5 times prinln("foo")创建IntWithTimes的对象,使方法{{1} }通过导入times隐式提供。

Helpers._

让我们考虑以下示例:

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)
    }
  }
}

显然是Scala和Akka的新手,到目前为止我不满意的理论是,使用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() create()通过将GraphDSL传递给RunnableGraph来创建Builder

为什么必须将其标记为implicit?如果离开,~>运算符将无法再解析 - 即使GraphDSL.Implicits._已明确导入。

1 个答案:

答案 0 :(得分:3)

implicit在Scala中有多个用例,其中一个是你提到的隐式类。但是,还有implicit parametersimplicit conversions。我建议阅读这些,这个答案的范围有点多,并且会不必要地复制信息。但请注意,隐式类主要是syntactic sugar for a class with an implicit conversion,因此它们的功能相同。

  

如果离开,那么〜>无法解析运算符 - 即使显式导入了GraphDSL.Implicits._。

这会将隐含的转化导入FlowOps,其中~>实际定义。此时Scala知道转换。但是,要实际执行此操作,需要隐式参数 b : Builder[_]。请查看Implicits中的转化定义:

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

现在您可以将任何Builder[_]标记为隐式,如果丢失,Scala会自动为您填写此参数。从Builder中删除implicit关键字意味着不再有任何隐含值可用于填充此参数,这意味着无法进行转换,随后方法~>无效。< / p>

然而,您可以自由地手动调用隐式转换并自行填写缺少的参数(绕过整个隐式参数功能),但相比之下,这看起来非常丑陋/冗长:

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