3

I am new to scala. I have written a function named calculateSubTotal with a list of product id and quantities.

At first the function will pick up a product from the database for each of the product id, then calculate the individual sub total and sum up with sub total. I would like return the calculated sub total. Calculation is OK but unfortunately it returns the initialized value rather than the calculated value. Whats with my code. The code is as:-

def calculateSubTotal(productIds: Seq[Int], quantities: Seq[Int]) = {
  var subTotal = 0.0
  for (index <- 0 to productIds.length - 1) {
    val productId = productIds(index)
    val quantity  = quantities(index)
    val futureProduct = Products.read(productId)
    for {
      product <- futureProduct
    } yield {
      val listPrice = product.get.listPrice
      subTotal += listPrice * quantity
    }
  }
  subTotal
}

Look the above function always returns 0.0 as I have initialized. What will be the correct code?

testuser
  • 793
  • 3
  • 13
  • 35

1 Answers1

1

The problem is that the resulting type of your Products.read() method is Future[Option[Product]], which means that in your current code it's executed on a different thread. The main thread (the one executing calculateSubTotal) doesn't wait for a successful execution of Products.read() and it returns the result (subTotal in this case) right away. This will allow nondeterministic results: sometimes subTotal won't be modified at all, sometimes it'll be modified partially and sometimes you'll get a proper result. The simplest solution would be to synchronously wait for Products.read() result:

import scala.concurrent.duration.Duration
import scala.concurrent.Await

Await.result(Products.read(productId), Duration.Inf)

The asynchronous solution would require rewriting calculateSubTotal in a way, that returns Future[Int].

Paweł Jurczenko
  • 4,431
  • 2
  • 20
  • 24