Search code examples
scalaakka-stream

Akka streams - why is an ActorSystem accepted as a Materalizer only when it is marked as implicit?


I'm looking at the akka streams quickstart tutorial and I wanted to understand how a piece of code works. The following code from the example prints out the values from 1 to 100 to the console:

import akka.stream.scaladsl._
import akka.{Done, NotUsed}
import akka.actor.ActorSystem

object Akka_Streams extends App{
  implicit val system: ActorSystem = ActorSystem("QuickStart")
  val source: Source[Int, NotUsed] = Source(1 to 100)

  source.runForeach(i => println(i))
}

What I don't understand is, when I change the code to the following and remove the implicit, the code no longer works. I get a type mismatch error (shown below the following code):

object Akka_Streams extends App{
  val system: ActorSystem = ActorSystem("QuickStart")
  val source: Source[Int, NotUsed] = Source(1 to 100)

  source.runForeach(i => println(i))(system)
}

Error:

type mismatch; found : akka.actor.ActorSystem required: akka.stream.Materializer source.runForeach(i => println(i))(system)

Why did this work before but not now? the source.runForeach method takes a Materalizer type so I wonder why this was working at all to begin with? From what I can see, an ActorSystem is not a Materalizer or a sub-type of it so I'm confused.


Solution

  • It is related to how Scala compiler converts ActorSystem to a Materializer

    It is done via implicit conversions with following method

     /**
       * Implicitly provides the system wide materializer from a classic or typed `ActorSystem`
       */
      implicit def matFromSystem(implicit provider: ClassicActorSystemProvider): Materializer =
        SystemMaterializer(provider.classicSystem).materializer
    

    It requires parameter provider to be implicit.

    So having implicit key is allowing the compiler to take an implicit actor system when it needs an instance of a Materializer, and such conversion is done without any need to explicitly define a materializer in the scope.