How to Run Different Functions in Parallel Scala - scala

How to run in parallel the two different functions that returns different datatype?
Here we have fruitFutures, and primeFutures. How can I utilize the Await.result function?
val fruits = List("apple", "orange", "mango", "banana")
val primeNums = List(2,3,5,7,11)
def executeFruit(fruit: String): Try[String] = {
Try {
s"executed $fruit"
}
}
def executePrime(prime: Int): Try[Int] = {
Try {
prime * 2
}
}
val fruitFutures: List[Future[Try[String]]] = for {
fruit <- fruits
} yield {
Future {
executeFruit(fruit)
}
}
val primeFutures: List[Future[Try[Int]]] = for {
prime <- primeNums
} yield {
Future {
executePrime(prime)
}
}
val futureResults = Await.result(Future.sequence(???), Duration.Inf)

You can try this:
val futureResults = for {
f <- Future.sequence(fruitFutures)
p <- Future.sequence(primeFutures)
} yield (f, p)
val (fruitResult, primeResult) =
Await.result(futureResults, Duration.Inf)
This will result:
List(Success(executed apple), Success(executed orange), Success(executed mango), Success(executed banana))
List(Success(4), Success(6), Success(10), Success(14), Success(22))

Related

Scala map is not gettin updated

I've written the following solution in scala for the three sum problem.
However the value in the map sums never gets updated.
Can someone explain why doesn't it get updated?
import collection.mutable.ListBuffer
object Solution {
def threeSum(nums: Array[Int]): List[List[Int]] = {
val sums = Map[Int, ListBuffer[(Int, Int)]]().withDefaultValue(ListBuffer())
for((a, aIndex) <- nums.view.zipWithIndex) {
for((b, bIndex) <- nums.view.zipWithIndex) {
if(aIndex != bIndex){
val sum = a + b
List(a, b).sorted match {
case List(a, b) => {
sums(sum) += ((a, b))
println(sums)
}
}
}
}
}
val result = ListBuffer[List[Int]]()
for(c <- nums){
val neg = c * -1
if(sums.contains(neg)){
val sumSet = sums(neg).toSet
for((a,b) <- sumSet) {
val triplet = List(a, b, c).sorted
result += triplet
}
}
}
result.toList
}
}

Getting compilation error when using for and yield

What is wrong with the following code snippet?
val loginInfoFuture: Future[LoginInfo] = credentialsProvider.authenticate(credentials)
for{loginInfo <- loginInfoFuture}{
println("in loginInfo future")
} yield Future{Ok(Json.toJson(JsonResultError("Invalid Body Type. Need Json")))}
I am seeing error in IDE - Error:(239, 17) ';' expected but 'yield' found.
} yield Ok(Json.toJson(JsonResultError("Invalid Body Type. Need Json")))
I tried a similar piece of code on REPL and that seem to work fine.
scala> import scala.concurrent.Future
import scala.concurrent.Future
scala> import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.ExecutionContext.Implicits.global
scala> val f:Future[Int] = Future{1}
f: scala.concurrent.Future[Int] = Future(Success(1))
scala> for(f1 <- f) yield f1
res0: scala.concurrent.Future[Int] = Future(<not completed>)
scala>
For reference, below is the full function
def signInUser = silhouette.UserAwareAction.async { implicit request => {
val body: AnyContent = request.body
val jsonBody: Option[JsValue] = body.asJson
jsonBody match {
case Some(json) => {
val userSignin: Option[UserSignin] = json.asOpt[UserSignin] //check if json conforms with UserProfile structure
userSignin match {
case Some(signinInfo) => { //format of JSON is correct
//Get signin info from JSON (email and password)
val credentials: Credentials = Credentials(signinInfo.signinInfo.email, signinInfo.signinInfo.password)
val authInfoRepository = new DelegableAuthInfoRepository(userRepo.passwordRepo)
val passwordHasherRegistory = new PasswordHasherRegistry(userRepo.passwordHasher)
val credentialsProvider = new CredentialsProvider(authInfoRepository, passwordHasherRegistory)
for{loginInfo <- loginInfoFuture}{ //for returns unit. Should use yield
println("in loginInfo future")
} yield Future{Ok(Json.toJson(JsonResultError("Invalid Body Type. Need Json")))}
}
case None => { //No signin info found
Future {
Ok(Json.toJson(JsonResultError("Invalid user. No Login info found")))
}
}
}
}
case None => {//NO Body
Future {
Ok(Json.toJson(JsonResultError("Invalid Body Type. Need Json")))
}
}
} //jsonBody match
}//async
}//def signin
for{loginInfo <- loginInfoFuture}{ //for returns unit. Should use yield
println("in loginInfo future")
} yield Future{Ok(Json.toJson(JsonResultError("Invalid Body Type. Need Json")))}
This is invalid. Your for/yield needs to be in the format:
for {
y <- z
x <- y
//etc
} yield {
//whatever
}
The println after the for but before the yield is throwing you. To get the result of the println inside the for/yield, you could to assign it to a value:
for {
y <- z
a = println(y) // will print out every y
x <- y
//etc
} yield {
//whatever
}
for/yield blocks are stupid like that. At least there are work-arounds though!
The following section is from scala's Future documentation:
def foo(): Unit = {
val f = Future { 5 }
val g = Future { 3 }
val h = for {
x: Int <- f // returns Future(5)
y: Int <- g // returns Future(3)
} yield x + y
}
You on the other hand try to do this:
def foo(): Unit = {
val f = Future { 5 }
val g = Future { 3 }
val h = for {
x: Int <- f // returns Future(5)
y: Int <- g // returns Future(3)
} {
println("whatever") // <<<<<<<<<
} yield x + y
}
The extra block of code that I point is what causing the compilation error which you did not add in your scala repl example.
This is how you can print within a Future:
def foo(): Unit = {
val f = Future {
println("5")
5
}
val g = Future {
println("3")
3
}
val h = for {
x: Int <- f // returns Future(5)
y: Int <- g // returns Future(3)
} yield x + y
}
Error:(239, 17) ';' expected but 'yield' found.
simply means that the for loop definition is wrong
So either with yield
for{loginInfo <- loginInfoFuture
//other conditions and statements
} yield //value to be returned
or without yield
for(loginInfo <- loginInfoFuture){
//value updated
}
are correct for loop definitions

Flatten future inside yield

In the code below x is type Future[Future[Int]] and I need to flatten it to become Future[Int]. How is this possible?
def times(a:Int, b:Int) = Future { a * b }
val x = for {
x1 <- Future { 1 }
x2 <- Future { 2 }
} yield {
val future = times(x1,x2)
future.map { result => result * 2 }
}
Use the same for-comprehension. As times returns Future taking input x1 and x2. You can use same for-comprehension to extract the value out of the future.
def times(a:Int, b:Int) = Future { a * b }
val x = for {
x1 <- Future { 1 }
x2 <- Future { 2 }
result <- times(x1,x2)
} yield (result * 2)
Remember for-comprehension is a syntactic sugar for flatMaps and one final map
The whole thing can be written as
Future { 1 }.flatMap { x1 => Future { 2 }.flatMap { x2 => times(x1, x2).map { result => result * 2 }}}
Warning: As you are creating data independent futures inline (inside the for-comprehension or inside the flatMap). These futures will execute sequentially.
As first and second futures are data independent. They can be executed parallelly if you have created them outside the for-comprehension or flatMap.
Flatten futures
Use flatMap to convert Future[Future[Int]] into Future[Int]
def times(a:Int, b:Int) = Future { a * b }
val x = (for {
x1 <- Future { 1 }
x2 <- Future { 2 }
} yield {
val future = times(x1,x2)
future.map { result => result * 2 }
}).flatMap(identity) // <--- notice flatMap here around the for-comprehension
For clarity above code can be re-written as
def times(a:Int, b:Int) = Future { a * b }
val x = for {
x1 <- Future { 1 }
x2 <- Future { 2 }
} yield times(x1,x2).map(_ * 2)
val finalResult = x.flatMap(identity)
Scala REPL
scala> :paste
// Entering paste mode (ctrl-D to finish)
def times(a:Int, b:Int) = Future { a * b }
val x = for {
x1 <- Future { 1 }
x2 <- Future { 2 }
} yield times(x1,x2).map(_ * 2)
val finalResult = x.flatMap(x => x)
// Exiting paste mode, now interpreting.
scala> finalResult
res0: scala.concurrent.Future[Int] = Future(Success(4))

scala trait members and derivated variables

Hi am trying to write a simple hill climbing algorithm in scala .
I have State and HillClimbing that are traits.
I define them as concrete classes when I apply them to the Graph problem.
In GraphHillClimbing I receive two errors. This is because I use GraphState instead of State (observe that GraphState is also a State).
How can I solve this?
trait State {
val loc = 0
def neighbours: List[State]
def get_loc():Int = return loc
}
class GraphState(loc:Int, g: Map[Int, List[Int]]) extends State {
def neighbours():List[GraphState] =
{
def neighboursAcc(l:List[Int], acc:List[GraphState], g:Map[Int, List[Int]]):List[GraphState] =
{
if(l.isEmpty) acc
else {
val new_neig = new GraphState(l.head, g)
neighboursAcc(l.tail, List(new_neig) ++ acc, g)
}
}
neighboursAcc(g(loc), List(), g)
}
}
trait HillClimbing {
val max_iteration = 4
val start:State
def cost(state:State):Double
private def argmin(costs:List[Double]):Int = {
val best = costs.min
costs.indexOf(best)
}
private def next_best(states:List[State]):State = {
val costs = states map(x => cost(x))
val pos = argmin(costs)
states(pos)
}
def minimize():State = {
def minimizeAcc(iteration:Int, state:State):State =
{
if(iteration > max_iteration) state
else {
val neigs = state.neighbours
val next_state = next_best(neigs)
minimizeAcc(iteration+1, next_state)
}
}
minimizeAcc(0, start)
}
}
class GraphHillClimbing(start:GraphState, goal:GraphState) extends HillClimbing {
// ERROR 1 = start was State and now it is GraphState
// ERROR 2 = cost should take a State
def cost(current_state:GraphState):Double = {
val distance = goal.get_loc() - current_state.get_loc()
if(distance > 0 ) distance
else -distance
}
}
object RunHillClimbing {
def main(args: Array[String]) {
val G = Map[Int, List[Int]](1->List(2, 4, 5), 2->List(1, 3, 4), 3->List(2, 6), 4->List(1, 2, 5), 5->List(1, 4), 6->List(3))
val start = new GraphState(1, G)
val goal = new GraphState(6, G)
val hc = new GraphHillClimbing(start, goal)
print(hc.minimize())
}
}
I think this can be solved using some type parameters with type bounds.
Also in your constructor for GraphHillClimbing you should use val to indicate that the parameter start is the concrete implementation of the abstract start.
trait State[+Self] {
Self =>
def loc:Int
def neighbours: List[Self]
def get_loc():Int = return loc
}
class GraphState(val loc:Int, g: Map[Int, List[Int]]) extends State[GraphState] {
def neighbours():List[GraphState] =
{
def neighboursAcc(l:List[Int], acc:List[GraphState], g:Map[Int, List[Int]]):List[GraphState] =
{
if(l.isEmpty) acc
else {
val new_neig = new GraphState(l.head, g)
neighboursAcc(l.tail, List(new_neig) ++ acc, g)
}
}
neighboursAcc(g(loc), List(), g)
}
}
trait HillClimbing[T<:State[T]] {
val max_iteration = 4
val start:T
def cost(state:T):Double
private def argmin(costs:List[Double]):Int = {
val best = costs.min
costs.indexOf(best)
}
private def next_best(states:List[T]):T = {
val costs = states map(x => cost(x))
val pos = argmin(costs)
states(pos)
}
def minimize():T = {
def minimizeAcc(iteration:Int, state:T):T =
{
if(iteration > max_iteration) state
else {
val neigs = state.neighbours
val next_state = next_best(neigs)
minimizeAcc(iteration+1, next_state)
}
}
minimizeAcc(0, start)
}
}
class GraphHillClimbing(val start:GraphState, goal:GraphState) extends HillClimbing[GraphState] {
def cost(current_state:GraphState):Double = {
val distance = goal.get_loc() - current_state.get_loc()
if(distance > 0 ) distance
else -distance
}
}
object RunHillClimbing {
def main(args: Array[String]) {
val G = Map[Int, List[Int]](1->List(2, 4, 5), 2->List(1, 3, 4), 3->List(2, 6), 4->List(1, 2, 5), 5->List(1, 4), 6->List(3))
val start = new GraphState(1, G)
val goal = new GraphState(6, G)
val hc = new GraphHillClimbing(start, goal)
print(hc.minimize())
}
}
What I get:
error: class GraphHillClimbing needs to be abstract, since:
it has 2 unimplemented members.
/** As seen from class GraphHillClimbing, the missing signatures are as follows.
* For convenience, these are usable as stub implementations.
*/
def cost(state: this.State): Double = ???
val start: this.State = ???
class GraphHillClimbing(start:GraphState, goal:GraphState) extends HillClimbing {
^
Replace GraphState in the class with State, because inheritance
demands you'll have to handle State not GraphState.
Then replace
val loc = 0
with
def loc = 0
So you can overwrite it in GraphState.

for comprehension from flatMap and future to future

I would like something like runProgram2 but currently that part does not compile. Is there a way to write it somewhat like runProgram2 but so it compiles..
package transformer
import scala.concurrent.{ExecutionContext, Promise, Future}
import ExecutionContext.Implicits.global
import java.util.concurrent.TimeUnit
import scala.concurrent.duration.Duration
object TestingForComprehensions2 {
def main(args: Array[String]) = {
val future1: Future[String] = runMyProgram()
future1.onSuccess {
case r:String => System.out.println("result="+r)
}
val future2: Future[String] = runMyProgram2()
future2.onSuccess {
case r:String => System.out.println("result="+r)
}
System.out.println("waiting")
Thread.sleep(600000)
}
def runMyProgram() : Future[String] = {
val future = serviceCall()
val middle = serviceCallWrap(future)
val future2 = middle.flatMap(serviceCall2)
val future3 = future2.map(processAllReturnCodes)
future3
}
def runMyProgram2() : Future[String] = {
for {
result1 <- serviceCall()
middle = serviceCallWrap(result1)
result2 <- serviceCall2(middle)
} yield processAllReturnCodes(result2)
}
def processAllReturnCodes(theMsg: String) : String = {
"dean"+theMsg
}
def serviceCall() : Future[Int] = {
val promise = Promise.successful(5)
promise.future
}
def serviceCallWrap(f:Future[Int]) : Future[Int] = {
f
}
def serviceCall2(count:Int) : Future[String] = {
val promise = Promise.successful("hithere"+count)
promise.future
}
}
serviceCallWrap expects a future, but you are passing an Int, first step would be to remove the result1 <- serviceCall() part and call directly middle = serviceCallWrap(serviceCall()).
Now middle is a future but serviceCall2 takes an Int, in this case you can extract the value from the future using middle <- serviceCallWrap(serviceCall()), all together:
def runMyProgram2() : Future[String] = {
for {
middle <- serviceCallWrap(serviceCall())
result2 <- serviceCall2(middle)
} yield processAllReturnCodes(result2)
}
If you want to keep the comprehension structure:
def runMyProgram2() : Future[String] = {
for {
result1 <- serviceCall()
middle <- serviceCallWrap(Future(result1))
result2 <- serviceCall2(middle)
} yield processAllReturnCodes(result2)
}
The only thing you can't keep (AFAIK) is the assignment expression for middle, if you want to keep that you need to change serviceCall2 signature. This approach though has exactly the same result as the first approach, it's only more verbose.
I think I have this figured out now. or at least this compiles so I can do it on a different line.....
def runMyProgram2() : Future[String] = {
for {
result1 <- serviceCall()
middle <- serviceCallWrap(Promise.successful(result1).future)
result2 <- serviceCall2(middle)
} yield processAllReturnCodes(result2)
}