7

My stream has a Flow whose outputs are List[Any] objects. I want to have a mapAsync followed by some other stages each of which processed an individual element instead of the list. How can I do that?

Effectively I want to connect the output of

Flow[Any].map { msg =>
  someListDerivedFrom(msg)
}

to be consumed by -

Flow[Any].mapAsyncUnordered(4) { listElement =>
  actorRef ? listElement
}.someOtherStuff

How do I do this?

anindyaju99
  • 465
  • 1
  • 5
  • 16

1 Answers1

13

I think the combinator you are looking for is mapConcat. This combinator will take an input argument and return something that is an Iterable. A simple example would be as follows:

implicit val system = ActorSystem()
implicit val mater = ActorMaterializer()

val source = Source(List(List(1,2,3), List(4,5,6)))
val sink = Sink.foreach[Int](println)

val graph =
  source.
    mapConcat(identity).
    to(sink)
graph.run

Here, my Source is spitting out List elements, and my Sink accepts the underlying type of what's in those Lists. I can't connect them directly together as the types are different. But if I apply mapConcat between them, they can be connected as that combinator will flatten those List elements out, sending their individual elements (Int) downstream. Because the input element to mapConcat is already an Iterable, then you only need to use the identify function in the body of mapConcat to make things work.

cmbaxter
  • 35,283
  • 4
  • 86
  • 95
  • 1
    Thank you. I was trying mapConcat a bit differently and that was not working. What exactly is the significance of "identity". – anindyaju99 Jul 19 '16 at 01:29
  • 1
    _identity_ is defined in _scala.Predef_ and is just what it looks like: a function which transforms something into itself. Very useful for passing as the function required by _map_, _flatMap_, etc. – Phasmid Jul 19 '16 at 01:45