在我的工作代码中涉及递归。我试图避免这种情况,因为如果谓词不成立,递归可能会太深。
case class Chan[T]() {
private var promise: Promise[T] = Promise[T]()
/** Binds a handler with the "write" in casu update() */
def this(handler: (T => Unit) => Unit) {
this
handler(update)
}
def filter(p: (T) => Boolean): Future[T] = {
apply().flatMap(value => if (p(value)) Future(value) else filter(p))
}
def apply(): Future[T] = {
promise = Promise[T]()
promise.future
}
def update(t: T): Unit = {
if (!promise.isCompleted) promise.success(t)
}
}
问题在于filter
方法。当不满足谓词时,将再次调用filter
,寻找符合参数的事件。由此堆栈将被填充,前面是StackOverflow: - )。
如何在循环或尾递归调用中重构代码,避免过多的堆栈使用?
答案 0 :(得分:1)
所以这里是上面提到的解决方案。 我希望这符合你的目的:
case class Chan[T]() {
private var pendingFilters: List[(T => Boolean, Promise[T])] = List.empty
/** Binds a handler with the "write" in casu update() */
def this(handler: (T => Unit) => Unit) {
this
handler(update)
}
def filter(p: (T) => Boolean): Future[T] = {
val promise = Promise[T]()
// add both the predicate and the promise to your pending filters
synchronized(pendingFilters = p -> promise :: pendingFilters)
promise.future
}
def update(t: T): Unit = {
synchronized {
// partition your pending filters into completed and uncompleted ones
val (completed, pending) = pendingFilters.partition(_._1(t))
pendingFilters = pending
completed
}.foreach{ case (_, promise) =>
// and finally complete the promises
promise.trySuccess(t)
}
}
}