Avenger
Avenger

Reputation: 877

Tail Recurson without Await

I have a scenario where the program ends before the future call executes when i warp the call to calltoFutureMethod(data) method in map.

So i had replaced it with Await.result but i do not want to use Await as it blocks but can not also do:

calltoFutureMethod(data) map{
result => sendData(newData)
}

as tail recursion does not allow it. Is there any other way without Await and Thred.sleep with tail recursion?

   @scala.annotation.tailrec
      def sendData(
      data: List[String]
      ): Unit =
    data match {
    case head::tail =>
         val result = for {
         p <- calltoFutureMethod(data)
         } yield p
         val putDataList = Await.result(result, 10.seconds)
         sendData(newData)
         }
    case Nil => ...
    }

    def callToFutureMethod(data: List[String]) =
    {
    Future
     {
     }
    }

Upvotes: 1

Views: 78

Answers (1)

Mateusz Kubuszok
Mateusz Kubuszok

Reputation: 27595

You don't need to use tail recursion if you map/flatMap on Future/IO/Task or any other structure which implements trampoline to be stack safe. So:

calltoFutureMethod(data) map {
  result => sendData(newData)
}

IS safe.

The fact that your program terminates is probably because the ExecutionContext you use is a daemon (e.g. ExecutionContext.Implicits.global) - JVM is allowed to terminate if all remaining threads are daemons, so either wait for the end of the future in your main function, or define/use ExecutionContext that is NOT a deamon, at least for these futures.

import java.util.concurrent.Executors

import scala.concurrent.ExecutionContext

// pick up whatever Executor you need
implicit val customExecutionContext: ExecutionContext =
  ExecutionContext.fromExecutor(Executors.newFixedThreadPool(10))

Upvotes: 3

Related Questions