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

Akka Streams: Why does the GraphDSL.Builder have to be marked as implicit?

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

根据 http://docs.scala-lang.org/overviews/core/implicit-classes.html,Scala 中 implicit class 的基本概念是为 5 times prinln("foo") 创建一个 IntWithTimes 的对象,使得方法 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)
    }
  }
}

让我们考虑以下示例:

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

显然是 Scala 和 Akka 的新手,到目前为止我不满意的理论是使用 GraphDSLcreate() 通过将 Builder 传递给它来创建 RunnableGraph

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

implicit 在 Scala 中有多个用例,其中之一是您提到的隐式 类 。但是,也有implicit parameters and implicit conversions. I recommend reading up on those, it's a bit much for the scope of this answer and would needlessly duplicate information. Note however that implicit classes are mostly ,所以它们的作用是一样的。

If left away, the ~> operators cannot be resolved anymore - even though GraphDSL.Implicits._ is explicitly imported.

这会将隐式 conversions 导入到 FlowOps,其中实际定义了 ~>。此时 Scala 知道转换。然而,要实际执行此操作,它需要一个隐式的 参数 b : Builder[_]。看看Implicits:

中的转换定义
implicit def fanOut2flow[I, O](j: UniformFanOutShape[I, O])(implicit b: Builder[_]): PortOps[O]

现在您可以将任何 Builder[_] 标记为隐式,如果缺少此参数,Scala 会自动为您填充。从您的构建器中删除 implicit 关键字意味着不再有任何隐式值可用于填充此参数,这意味着转换无法发生,随后方法 ~> 不可用。

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

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