没有等待的尾递归
Tail Recurson without Await
我有一个场景,当我在映射中扭曲对 calltoFutureMethod(data) 方法的调用时,程序在未来调用执行之前结束。
所以我用 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
{
}
}
如果在 Future
/IO
/Task
或任何其他结构上 map
/flatMap
或任何其他结构,则不需要使用尾递归实现蹦床是堆栈安全的。所以:
calltoFutureMethod(data) map {
result => sendData(newData)
}
安全。
您的程序终止的事实可能是因为您使用的 ExecutionContext
是 a daemon (e.g. ExecutionContext.Implicits.global
) - 如果所有剩余线程都是守护进程,则允许 JVM 终止,因此要么等待future 在你的 main
函数中,或者 define/use ExecutionContext
不是守护进程,至少对于这些 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))
我有一个场景,当我在映射中扭曲对 calltoFutureMethod(data) 方法的调用时,程序在未来调用执行之前结束。
所以我用 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
{
}
}
如果在 Future
/IO
/Task
或任何其他结构上 map
/flatMap
或任何其他结构,则不需要使用尾递归实现蹦床是堆栈安全的。所以:
calltoFutureMethod(data) map {
result => sendData(newData)
}
安全。
您的程序终止的事实可能是因为您使用的 ExecutionContext
是 a daemon (e.g. ExecutionContext.Implicits.global
) - 如果所有剩余线程都是守护进程,则允许 JVM 终止,因此要么等待future 在你的 main
函数中,或者 define/use ExecutionContext
不是守护进程,至少对于这些 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))