Hey! I have two "remote" calls. I want `product` ...
# arrow
j
Hey! I have two "remote" calls. I want
product
to be called first and if that succeeds
add
should be called. But in the following code
product
and
add
is called concurrently. How can I make them not concurrent? 😃
Copy code
import java.io.IOException
import arrow.core.computations.either
import arrow.core.Either
import arrow.core.Either.Left
import arrow.core.Either.Right
import arrow.core.getOrHandle

data class Error(val errorString: String, val exception: Exception?)

fun <A> remote(f: () -> A): A = if (Math.random() > 0.2) f() else throw IOException("boom!")

fun <A> trap(errorString: String, f: () -> A): Either<Error, A> =
    try { Right(f()) }
    catch (e: Exception) { Left(Error(errorString, e)) }

fun multiply(a: Int, b: Int): Either<Error, Int> = trap("multiplication failed") { remote { a * b } }

fun add(a: Int, b: Int): Either<Error, Int> = trap("addition failed") { remote { a + b } }

// If fetching `product` is failing `sum` should not be called at all.
suspend fun calculate(a: Int, b: Int): Either<Error, Int> =
    either<Error, Int> {
        val product = multiply(a, b).bind()
        val sum = add(a, b).bind()
        sum }

suspend fun main() {
    println(calculate(2, 10).getOrHandle { it.errorString })
    println(calculate(2, 10).getOrHandle { it.errorString })
}
s
Based on this code, they should run sequentially, not concurrently. Is this the exact code or a simplified example? What makes you conclude that the two remote calls are running concurrently?
j
Ahh! Ive made a small error when playing around. Just as you say @Sam it doesn't run concurrently. This code confirms that I think.
Copy code
#+HEADER: :classpath /Users/john.herrlin/.m2/repository/io/arrow-kt/arrow-core-jvm/1.1.3/arrow-core-jvm-1.1.3.jar:/Users/john.herrlin/.m2/repository/io/arrow-kt/arrow-continuations-jvm/1.1.3/arrow-continuations-jvm-1.1.3.jar
#+BEGIN_SRC kotlin :results output code
  import java.io.IOException
  import arrow.core.computations.either
  import arrow.core.Either
  import arrow.core.Either.Left
  import arrow.core.Either.Right
  import arrow.core.getOrHandle

  data class Error(val errorString: String, val exception: Exception?)

  fun <A> remote(f: () -> A): A = throw IOException("boom!")

  fun <A> trap(errorString: String, f: () -> A): Either<Error, A> =
      try { Right(f()) }
  catch (e: Exception) { Left(Error(errorString, e)) }

  fun multiply(a: Int, b: Int): Either<Error, Int> {
      println("running multiply")
      return trap("multiplication failed") { remote { a * b } }
  }

  fun add(a: Int, b: Int): Either<Error, Int> {
      println("running add")
      return trap("addition failed") { a + b }
  }

  suspend fun calculate(a: Int, b: Int): Either<Error, Int> =
      either<Error, Int> {
          val product = multiply(a, b).bind()
          val sum = add(a, b).bind()
          sum }

  suspend fun main() {
      println(calculate(2, 10).getOrHandle { it.errorString })
      println(calculate(2, 10).getOrHandle { it.errorString })
      println(calculate(2, 10).getOrHandle { it.errorString })
  }
#+END_SRC

#+RESULTS:
#+begin_src kotlin
  running multiply
  multiplication failed
  running multiply
  multiplication failed
  running multiply
  multiplication failed
#+end_src
Thank you for helping me out!
s
rubber duck 😄