I'm taking the Reactive programming course on Coursera and when doing one of the assignments I came across something weird. Anyways I added a few methods to the Future Companion object via this extension
implicit class FutureCompanionOps[T](val f: Future.type) extends AnyVal {
/** Returns a future that is always completed with `value`.
*/
def always[T](value: T): Future[T] = Future(value)
/** Returns a future that is never completed.
*
* This future may be useful when testing if timeout logic works correctly.
*/
def never[T]: Future[T] = Promise().future
/** 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.
*/
def all[T](fs: List[Future[T]]): Future[List[T]] = {
val resPr = Promise[List[T]]()
def function( in: List[Future[T]], fxs:Future[List[T]] ): Future[List[T]] =
{
if(in.isEmpty) fxs
else
function( in.tail, for { i <- in.head ; xs <- fxs } yield { i :: xs } )
}
function( fs, resPr.success(Nil).future )
}
}
i then wrote this on a Scala WorkSheet in Eclipse
object TestSheet {
val tempPr = Promise[Boolean]()
val anotherFuLs = List( Future.always(true), Future.always(false), tempPr.future )
//> anotherFuLs : List[scala.concurrent.Future[Boolean]] = List(scala.concurren
//| t.impl.Promise$DefaultPromise@a19b1de, scala.concurrent.impl.Promise$Default
//| Promise@1cec6b00, scala.concurrent.impl.Promise$DefaultPromise@625dcec6)
val crapFut = Future.all(anotherFuLs) //> crapFut : scala.concurrent.Future[List[Boolean]] = scala.concurrent.impl.Pr
//| omise$DefaultPromise@6564dbd5
crapFut.isCompleted //> res3: Boolean = false
tempPr.success(false) //> res4: nodescala.TestSheet.tempPr.type = scala.concurrent.impl.Promise$Defaul
//| tPromise@625dcec6
crapFut.isCompleted //> res5: Boolean = true
crapFut onComplete {
case Success(ls) => println( ls )
case Failure(e) => println( "Failed with Exception " + e )
}
}
no matter what I can't get the Scala Work Sheet to print out the values of the resulting List. However when I write a unit test and run scala test, I have no problem comparing the final resulting list. Is this a bug in scala worksheet when working with asynchronous stuff ?
This is the unit test
test("A composed future with all should complete when all futures complete") {
val tempPr = Promise[Boolean]()
val lsFu = List( Future.always(true), Future.always(false), tempPr.future );
val fuL = Future.all( lsFu )
fuL onComplete { case Success(ls) => println( "This got done" ); assert( ls === List( true, false, true ), "I should get back the expected List" )
case Failure(ex) => assert( false, "Failed with Exception " + ex ) }
assert( fuL.isCompleted === false, "The resulting Future should not be complete when the depending futures are still pending" )
tempPr.success(true)
}
Future.successful
does what youralways
method does. Similarly,Future.sequence
seems to do the same as yourall
– Firdausi