title: Akka/Scala: mapping Future vs pipeTo
body: <p>In <code>Akka</code> actors, are there any differences - in terms of number of threads being used, or thread locking - between sending a <code>Future</code> result to another actor by:</p>
  
  <p>A. mapping the <code>Future</code> to function that <code>tell</code> the result to the actor.</p>
  
  <p>B. defining an <code>onSuccess</code> callback on the future, which <code>tell</code> the result to the actor.</p>
  
  <p>C. piping the <code>Future</code> result to the actor with <code>pipeTo</code>.</p>
  
  <p>Some of these options are discussed in a previous question:</p>
  
  <p><a href="https://stackoverflow.com/questions/16401376/akka-send-a-future-message-to-an-actor">Akka: Send a future message to an Actor</a></p>
  
  <p><strong>Which one of the three is the preferred way to do it, and why?</strong></p>
  
  <p><strong>Also,</strong> I would like to know, if <code>receive</code> should be of type <code>Any =&gt; Unit</code>, then <strong>why does the code compile</strong> when in some cases the partial function of <code>receive</code> returns a <code>Future</code>, not <code>Unit</code>? </p>
  
  <p>Here is a code example of the three options that I mentioned above:</p>
  
  <pre><code>import akka.actor.{Actor, ActorRef, ActorSystem, Props}
  import akka.pattern.ask
  import akka.util.Timeout
  import akka.pattern.pipe
  
  import scala.concurrent.Future
  import scala.concurrent.duration._
  import scala.language.postfixOps
  import scala.util.Success
  
  class ActorIncrement extends Actor {
  
    def receive = {
      case i: Int =&gt;
        println(s"increment $i")
        sender ! i + 1
    }
  }
  
  class ActorEven extends Actor {
  
    def receive = {
      case i: Int =&gt;
        println(s"$i is even")
    }
  }
  
  
  class ActorOdd extends Actor {
  
    def receive = {
      case i: Int =&gt;
        println(s"$i is odd")
    }
  }
  
  class MyActor(actorIncrement: ActorRef, actorEven: ActorRef, actorOdd: ActorRef) extends Actor {
    import scala.concurrent.ExecutionContext.Implicits.global
  
    implicit val timeout = Timeout(5 seconds)
  
    def receive = {
      case i: Int if i % 2 == 0 =&gt;
        println(s"receive a: $i")
        actorIncrement ? i map {
          case j: Int =&gt;
            println(s"$j from increment a")
            actorOdd ! j
        }
      case i: Int =&gt;
        println(s"receive b: $i")
        val future: Future[Any] = actorIncrement ? i
        future onSuccess {
          case i: Int =&gt;
            println(s"$i from increment b")
            actorEven ! i
        }
  
      case s: String =&gt;
        println(s"receive c: $s")
        (actorIncrement ? s.toInt).mapTo[Int] filter(_ % 2 == 0) andThen { case Success(i: Int) =&gt; println(s"$i from increment c") } pipeTo actorEven
    }
  }
  
  object TalkToActor extends App {
  
    // Create the 'talk-to-actor' actor system
    val system = ActorSystem("talk-to-actor")
  
    val actorIncrement = system.actorOf(Props[ActorIncrement], "actorIncrement")
    val actorEven = system.actorOf(Props[ActorEven], "actorEven")
    val actorOdd = system.actorOf(Props[ActorOdd], "actorOdd")
  
    val myActor = system.actorOf(Props(new MyActor(actorIncrement, actorEven, actorOdd)), "myActor")
  
    myActor ! 2
    myActor ! 7
    myActor ! "11"
  
    Thread.sleep(1000)
  
    //shutdown system
    system.terminate()
  }
  </code></pre>