Description of the method :
Given a list of futures
fs, returns the future holding the list of values of all the futures fromfs. The returned future is completed only once all of the futures infshave been completed. The values in the list are in the same order as corresponding futuresfs. If any of the futuresfsfails, the resulting future also fails.
This is what I did :
implicit class FutureCompanionOps[T](val f: Future.type) extends AnyVal {
/***
//Some others method
***/
def all[T](fs: List[Future[T]]): Future[List[T]] = async {
var fsVar = fs;
val l = List()
while(fsVar.nonEmpty){
await{fsVar.head} :: l
fsVar = fsVar.tail
}
l
}
}
But I get the following compilation error at this line def all[T](fs: List[Future[T]]): Future[List[T]] = async { :
implementation restriction: nested class is not allowed in value class This restriction is planned to be removed in subsequent releases.
Could someone explain me this error and show me a workaround ?
This specific problem can be solved by moving that method outside the value class (FutureCompanionOps).
def allOutside[T](fs: List[Future[T]]): Future[List[T]] = async {
var fsVar = fs;
val l = Nil
while(fsVar.nonEmpty){
await{fsVar.head} :: l
fsVar = fsVar.tail
}
l.toList
}
implicit class FutureCompanionOps[T](val f: Future.type) extends AnyVal {
/***
//Some others method
***/
def all[T](fs: List[Future[T]]): Future[List[T]] = allOutside(fs)
}
Even the FAQ on the course page provides no further explanation on what is going on here, only that the feature is experimental. An async{} leads into a macro from where it becomes difficult to follow so ... probably somewhere along the line a nested class is created which is not allowed in value classes according to this article.
You are also advised to not use async{} and await{} at all as of now.
N.b. you're code will not work but I should not spoil the fun as the question was not about that
From the FAQ:
The Scala Async feature is nearing its first release and is partly experimental.
As a workaround for using Scala Async in value classes, consider moving the async invocation outside of the value class using the following trick:
class FutureOps[T](f: Future[T]) extends AnyVal {
def foo: Future[T] = fooImpl(f)
}
def fooImpl(f: Future[T]) = async {
val x = await { f }
throw new Exception
}
If that or other code juggling and refactoring does not solve the problem, consider using regular functional combinators like map, flatMap, continueWith and the rest of their friends.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With