Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"implementation restriction: nested class is not allowed in value class This restriction is planned to be removed in subsequent releases."

Tags:

scala

Description of the method :

Given a list of futures fs, returns the future holding the list of values of all the futures from fs. The returned future is completed only once all of the futures in fs have been completed. The values in the list are in the same order as corresponding futures fs. If any of the futures fs 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 ?

like image 696
user2336315 Avatar asked Nov 27 '13 20:11

user2336315


2 Answers

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

like image 200
mzn Avatar answered Sep 22 '22 09:09

mzn


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.

like image 26
OlivierBlanvillain Avatar answered Sep 23 '22 09:09

OlivierBlanvillain