def computeComplexNumber: () ⇒ Future[Int] =
() ⇒
Future {
println("Computing complex number ...")
Int.MaxValue
}
def convert(f: () ⇒ Future[Int]): Future[() ⇒ Int] = ???
convert(computeComplexNumber)
Is it possible to implement convert
method with above signature with condition that when convert(computeComplexNumber)
is called, nothing gets printed unless you do this
Await.result(convert(computeComplexNumber), 5.seconds)()
I don't see any way to do it without blocking inside convert
. There is simply no way to get hold of an instance of Future[X]
inside of convert
, without invoking f
. But once you invoke f
, the Future { ... }
will eagerly start to evaluate the block with the println
, and produce an output.
You probably want to take a look at scalaz.concurrent.Task
instead.
If you want to convert () => Future[Int]
to () => Int
you have to wait for the result of the Future
like this:
def convert(f: () ⇒ Future[Int]): Future[() ⇒ Int] =
Future{
() => Await.result(f(), Duration.Inf)
}
Then
val f = convert(computeComplexNumber) // Get Future
val g = Await.result(f, Duration.Inf) // Get Function
g() // Call function
The output will not appear until you call g
.
At the core of this question is this function signature:
def convert(f: () ⇒ Future[Int]): Future[() ⇒ Int]
There is also a requirement that (in paraphrase)
f
is not invoked until the returned function is invoked
Also, I am assuming that the Int
in the result is the value returned by the Future
in the argument, not just some random number!
The return type of the input function is Future[Int]
and the return type of the output function is Int
. The first is an asynchronous result and the second is a synchronous result. Any solution must therefore convert from asynchronous Future[Int]
to synchronous Int
. This means Await.result
or something similar.
There is also a requirement that the input function is not executed until the output function is executed. This means that it must be called inside the returned function which, in turn, means that the Await.result
must be called inside the returned function.
The solution above has the function signature of convert
that is required by the question. It also does not invoke f
until the function returned by convert
is executed, which was the other requirement.
This implementation of convert
is not blocking; it returns immediately with a Future
value. It does not invoke f
, it just returns a function that does.
There is some dispute about what it means to block inside a function, or for one function to invoke another. Blocking and invoking are processes that that happen during the execution of a function. Therefore a sensible definition of these things happening "inside" a function would be that they happen between the execution of the entry point of the function and the execution of the exit point of the function. Using this definition it is clear that the solution does not block inside the function or invoke f
inside the function.
The questioner has also commented that Await.result
should not be called anywhere. Unfortunately, as explained above, this is not possible because the requirement is to convert an asynchronous result into a synchronous result.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With