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 infs
have been completed. The values in the list are in the same order as corresponding futuresfs
. If any of the futuresfs
fails, 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