无处不在的形状和异步计算

时间:2016-10-13 09:26:31

标签: shapeless

“无形状”功能概述包含使用everywhere函数recursively transform a tree, by applying a given function的示例:

object inc extends ->((i: Int) => i + 1)

everywhere(inc)(tree)

我的问题:如果我们有asyncInc函数返回scala.concurrent.Future[Int],那么如何实现asyncEverywhere函数,该函数将返回Future修改后的Tree {1}}?

用法如下:

object asyncInc extends ->((i: Int) => Future { i + 1 } )

val treeFuture: Future[Tree[Int]] = asyncEverywhere(asyncInc)(tree)

1 个答案:

答案 0 :(得分:1)

如果我要编写asyncEverywhere方法,我会调用everywhere两次,并传递不同的函数。

第一个是副作用身份功能。 作为副作用,它将启动适当的Future并将其添加到可变列表中。 当遍历的第一遍完成时,我得到Future s的列表。

现在,我可以致电Future.sequence将其转换为Future个列表。我在此map上调用Future来转换以下列表 办法: - 我在everywhere上拨打Tree,这次是另一个功能。第二个函数只是将其后续结果从列表中拉出,从左开始(请记住,这将是一个可变列表)。由于列表的大小与处理的元素数相匹配。

这可能是这样的:

import scala.concurrent._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
import scala.language.postfixOps

def asyncEverywhere[T](asyncF: T => Future[T], tree: Tree[T])
  (implicit ec: ExecutionContext) = {

  val queue = scala.collection.mutable.Queue[Future[T]]()

  object enqueueFutures extends ->({ (i: T) =>
    queue.enqueue(asyncF(i))
    i
  })

  everywhere(enqueueFutures)(tree)

  Future.sequence(queue) map { q =>
    object dispenseResults extends (T -> T)(_ => q.dequeue())
    everywhere(dispenseResults)(tree)
  }
}

println(Await.result(
  asyncEverywhere(
    (i: Int) => Future { i + 1 },
    tree),
  1 minute))