Хвост Recurson без Await - PullRequest
       12

Хвост Recurson без Await

1 голос
/ 02 апреля 2020

У меня есть сценарий, в котором программа заканчивается до того, как будет выполнен будущий вызов, когда я деформирую вызов метода calltoFutureMethod (data) в map.

Поэтому я заменил его на Await.result, но я не хочу использовать Await, поскольку он блокирует, но также не может:

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

, поскольку хвостовая рекурсия не позволяет этого. Есть ли другой способ без Await и Thred.sleep с хвостовой рекурсией?

   @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
     {
     }
    }

1 Ответ

3 голосов
/ 02 апреля 2020

Вам не нужно использовать хвостовую рекурсию, если вы map / flatMap на Future / IO / Task или любой другой структуре, которая реализует батут для безопасности стека. Итак:

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

IS безопасен.

Тот факт, что ваша программа завершается, возможно, потому что ExecutionContext вы используете демон (например, ExecutionContext.Implicits.global) - JVM разрешается завершать, если все остальные потоки являются демонами, поэтому либо дождитесь конца будущего в вашей функции main, либо определите / используйте ExecutionContext, который НЕ является демоном, по крайней мере для этого будущего.

import java.util.concurrent.Executors

import scala.concurrent.ExecutionContext

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