Home > OS >  Scala - Executing every element until they all have finished
Scala - Executing every element until they all have finished

Time:05-25

I cannot figure out why my function invokeAll does not give out the correct output/work properly. Any solutions? (No futures or parallel collections allowed and the return type needs to be Seq[Int])

def invokeAll(work: Seq[() => Int]): Seq[Int] = {
        //this is what we should return as an output "return res.toSeq"

        //res cannot be changed!
        val res = new Array[Int](work.length)

    var list = mutable.Set[Int]()
    var n = res.size
    val procedure = (0 until n).map(work => 
      new Runnable {
        def run {
          //add the finished element/Int to list
          list  = work 
        }
      }
    )

    val threads = procedure.map(new Thread(_))
    threads.foreach(x => x.start())
    threads.foreach (x =>  (x.join()))
  
    res    list
    //this should be the final output ("return res.toSeq")
    return res.toSeq
  }

CodePudding user response:

OMG, I know a java programmer, when I see one :) Don't do this, it's not java!

val results: Future[Seq[Int]] = Future.traverse(work)

This is how you do it in scala.

This gives you a Future with the results of all executions, that will be satisfied when all work is finished. You can use .map, .flatMap etc. to access and transform those results. For example val sumOfAll: Future[Int] = results.map(_.sum)

Or (in the worst case, when you want to just give the result back to imperative code), you could block and wait on the future to get ahold of the actual result (don't do this unless you are absolutely desperate): Await.result(results, 1 year)

If you want the results as array, results.map(_.toArray) will do that ... but you really should not: arrays aren't really a good choice for the vast majority of use cases in scala. Just stick with Seq.

CodePudding user response:

The main problem in your code is that you are using fixed size array and trying to add some elements using (concatenate) operator: res list. It produces new Seq but you don't store it in some val. You could remove last line return res.toSeq and see that res lest will be return value. It will be your work.length array of zeros res with some list sequence at the end. Try read more about scala collections most of them immutable and there is a good practice to use immutable data structures. In scala Arrays doesn't accumulate values using operator in left operand. Array's in scala are fixed size.

  • Related