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.
Explanation in response to comments
The question
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 issues
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
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.
The comments
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.
Maybe something like this would work:
def computeComplexNumber: () => Future[Int] = () =>
Future {
delay(4.seconds.fromNow)
println("Computing complex number ...")
Int.MaxValue
}
def convert(f: () => Future[Int]): Future[() => Int] = {
f().map( m => () => m)
}
def delay(dur:Deadline) = {
Try(Await.ready(Promise().future, dur.timeLeft))
}
Related
I'm learning Scala and just getting familiar with syntax. I see that Future.apply takes a function as the work to do.
The following works perfectly:
val future = Future { doWork(1) }
However just for experimentation I tried some other ways to do it, and neither work appropriately.
val future = Future(() => doWork(1))
This results in the lambda becoming the completion value of the future, instead of the return value of doWork(1).
val work: () => Int = () => doWork(index)
val future = Future(work)
The same situation here. Could someone explain why passing the function as the work to be done is instead resulting in the function actually becoming the return value of the work being done. Also how would I go about this. Thanks!
The signature of method called in Future {...} is def apply[T](body: =>T) where => T is a by-name parameter. See this documentation for more info.
By-name parameters are only evaluated when used.
In examples
Future(() => doWork(1))
and
val work: () => Int = () => doWork(index)
val future = Future(work)
You are passing as by-name parameter function of type () => Int or same as Function0[Int]. This function is returned in the Future when by-name parameter is evaluated.
The function is not evaluated as Future does not call apply or ().
It will be more understandable if you add type parameters to the Future in all examples. If doWork returns Int. In this case Future { doWork(1) } is Future[Int] whereas it is Future[Function0[Int]] in the second and third examples.
The correct usage would be
val work: () => Int = () => doWork(index)
val future = Future(work())
The andThen meaning I learned from this answer is a function composer.
Say that
f andThen g andThen h
will equal to
h(g(f(x)))
This implies the h function will receive input from g(f(x))
But for the andThen in Future, all the closure of the following andThen always receives the result from the original Future.
Future{
1
}.andThen{ case Success(x) =>
println(x) // print 1
Thread.sleep(2000)
x * 2
}.andThen{ case Success(x) =>
println(x) // print 1
Thread.sleep(2000)
x * 2
}
compare to
val func: Function1[Int, Int] = { x: Int =>
x
}.andThen { y =>
println(y) // print 1
y * 2
}.andThen { z =>
println(z) // print 2
z * 2
}
func(1)
What is the reason to make Future::andThen(s) receive all the same result from original Future instead of chaining Future? I've observed that these chained andThen will be executed sequentially, so the reason may not be for parallel purpose.
scala.concurrent.Future is designed as compromise of two asynchronous approaches:
Object-oriented observer which allows binding of asynchronous handlers
Functional monad which offers rich functional composition capabilities.
Reading Future.andThen's docs:
Applies the side-effecting function to the result of this future, and
returns a new future with the result of this future.
So andThen is most likely from OOP universe. To gain similar similar result to Function1.andThen you could use map method :
Future(1).map {_ * 2}.map {_ * 2}
andThen differs from onComplete with one little thing: resulting Future of andThen still returning same result, but will wait until supplied observer will return or throw something. That's why there is written in the docs:
This method allows one to enforce that the callbacks are executed in a
specified order.
Also note third line from docs:
Note that if one of the chained andThen callbacks throws an exception,
that exception is not propagated to the subsequent andThen callbacks.
Instead, the subsequent andThen callbacks are given the original value
of this future.
So it' completely do nothing with new Future's result. Could not even spoil it with it's ownt exception. This andThen and onComplete just sequential and parallel binding of observers.
Let me sum up this nice discussion.
Say, we have tf: Future[T] =..., and two functions, f: T => U and g: U => V
We can do vf: Future[V] = tf map f map g, same asvf: Future[V] = tf map (f andThen g)
In another use case, having fp: PartialFunction[T, U] and gp: PartialFunction[U, V],
we can run tf1: Future[T] = tf andThen fp andThen gp - these partial functions will be called on the value that tf produces, with no outside effect - only side effects happen. This sequence waits for fp before calling gp.
Yet another future operation, onComplete, works like this: having f: Try[T] => U, the call tf onComplete f will call f even if the future ended with an error; the result of tf onComplete f is of type Unit.
Also, if your function f produces a Future, you will need to use flatMap.
I am going through the Principels of Reactive Programming course at Coursera and noticed few times a notation which I cannot completely comprehend. So I hope you can help me to understand.
Here is the code snippet:
def retry(noTimes:Int)(block: => Future[T]): Future[T] = {
val ns: Iterator[Int] = (1 to noTimes).iterator
val attempts: Iterator[Future[T]] = ns.map(_ => () => block)
val failed = Future.failed(new Exception)
attempts.foldLeft(failed) ((a, block) => a recoverWith {block()})
}
It is not clear to me why in the attempts value definition it is not simply ns.map(_ => block) ?
Type of the attempts value is Iterator[Future[T]] and map as it written in the snippet seems to me should produce Iterator[() => Future[T]]. Could you help to grasp it?
With this:
ns.map(_ => block)
block would be executed directly, that's not what the author would want.
Similar to Call-By-Value parameter.
However, with this:
ns.map(_ => () => block), it is similar to Call-By-Name parameter, meaning that the block code would be executed only when explicitly called in the underlying function.
If I correctly remembered, the author of the course was saying something like:
"Sit down, take a coffee and deeply analyse the function in order to figure out why we need to execute the block code lazily" ;)
UPDATE-------
In the wrapping method's signature, block is declared as a call-by-name parameter:
block: => Future[T]
Therefore, the Future[T] well corresponds to () => block explaining why:
val attempts: Iterator[Future[T]] is not val attempts: Iterator[() => Future[T]]
specifically, what is the difference for following two definitions:
def func(f: () => String) = f()
def func1(s: String) = s
I wrote some codes to test them, it seems they produce the same result; are those two definitions just the same in this scenario; or they do have some difference?
var x = 1
def f() = {
x = x + 1
s"$x"
}
println(func1(f))
println(func1(f))
println(func1(f))
println(func(f))
println(func(f))
println(func(f))
They are perhaps the same in THIS scenario, but there are lots of other scenarios when a () => A and a A are much different. () => A is referred to as a thunk and is used to pass a piece of delayed computation to a function. The body of the "thunk" doesn't get evaluated until the function called decides to evaluate it. Otherwitse, the value of the argument being passed in is evaluated by the caller.
Consider this example, where there IS a difference between the version that takes a thunk and the version that just takes a value:
object Thunk {
def withThunk(f: () ⇒ String): Unit = {
println("withThunk before")
println("the thunk's value is: " + f())
println("now the thunk's value is: " + f())
}
def withoutThunk(f: String): Unit = {
println("withoutThunk before")
println("now the value's value is: " + f)
}
def main(argv: Array[String]): Unit = {
withThunk { () ⇒ println("i'm inside a thunk"); "thunk value" }
println("------------")
withoutThunk { println("i'm not inside a thunk"); "just a value" }
}
}
This program will demonstrate some differences. In the thunk version, you see "withThunk before" get printed before the first time "i'm inside a thunk" gets printed, which gets printed twice, since f() is evaluated twice. In the non-thunk version, the "I'm not inside a thunk" gets printed before "withoutThunk before", since this is evaluated before being sent to the function as an argument.
def func(f: () => String) = f()
This one accepts as parameter a function that returns a string.
def func1(s: String) = s
While this one simple requires a String as parameter
Aside from the minor technical difference above, in this scenario they seem to function the same. However, the function parameter is potentially more powerful as it is a function that can derive its return value from several other operations. I think however, the main difference that the function parameter allows you to decide when the value is derived.
def func(f: () => String) = f()
def func1(s: String) = s
println(func1(f)) // in this case f is evaluated first, its value is used in func1.
println(func(f)) // in this case f is NOT evaluated, but passed as it is to func.
// It is upto func to call f whenever needed, or even not call it.
It is this "lazy" evaluation of f, that makes func more useful, for instance f can be passed to some other higher order functions, or it can be called asynchronously.
I want to add an example for the use of () => String.
def printFuncResult(f: () => String) = println(f() + " " + f())
def ran = () => Math.random.toString
printFuncResult(ran)
printFuncResult(Math.random.toString)
When you pass a function like ran then you will most likely have two different values printed (randomness is involved here). When you pass a fixed Random number then it will be printed twice.
As you can see: when you have a function as a parameter it might result in a different value each time it is used in printFuncResult. This is not possible when you just put a String parameter.
This is a follow-up to my previous question
Suppose I want to create a future with my function but don't want to start it immediately (i.e. I do not want to call val f = Future { ... // my function}.
Now I see it can be done as follows:
val p = promise[Unit]
val f = p.future map { _ => // my function here }
Is it the only way to create a future with my function w/o executing it?
You can do something like this
val p = Promise[Unit]()
val f = p.future
//... some code run at a later time
p.success {
// your function
}
LATER EDIT:
I think the pattern you're looking for can be encapsulated like this:
class LatentComputation[T](f: => T) {
private val p = Promise[T]()
def trigger() { p.success(f) }
def future: Future[T] = p.future
}
object LatentComputation {
def apply[T](f: => T) = new LatentComputation(f)
}
You would use it like this:
val comp = LatentComputation {
// your code to be executed later
}
val f = comp.future
// somewhere else in the code
comp.trigger()
You could always defer creation with a closure, you'll not get the future object right ahead, but you get a handle to call later.
type DeferredComputation[T,R] = T => Future[R]
def deferredCall[T,R](futureBody: T => R): DeferredComputation[T,R] =
t => future {futureBody(t)}
def deferredResult[R](futureBody: => R): DeferredComputation[Unit,R] =
_ => future {futureBody}
If you are getting too fancy with execution control, maybe you should be using actors instead?
Or, perhaps, you should be using a Promise instead of a Future: a Promise can be passed on to others, while you keep it to "fulfill" it at a later time.
It's also worth giving a plug to Promise.completeWith.
You already know how to use p.future onComplete mystuff.
You can trigger that from another future using p completeWith f.
You can also define a function that creates and returns the Future, and then call it:
val double = (value: Int) => {
val f = Future { Thread.sleep(1000); value * 2 }
f.onComplete(x => println(s"Future return: $x"))
f
}
println("Before future.")
double(2)
println("After future is called, but as the future takes 1 sec to run, it will be printed before.")
I used this to executes futures in batches of n, something like:
// The functions that returns the future.
val double = (i: Int) => {
val future = Future ({
println(s"Start task $i")
Thread.sleep(1000)
i * 2
})
future.onComplete(_ => {
println(s"Task $i ended")
})
future
}
val numbers = 1 to 20
numbers
.map(i => (i, double))
.grouped(5)
.foreach(batch => {
val result = Await.result( Future.sequence(batch.map{ case (i, callback) => callback(i) }), 5.minutes )
println(result)
})
Or just use regular methods that return futures, and fire them in series using something like a for comprehension (sequential call-site evaluation)
This well known problem with standard libraries Future: they are designed in such a way that they are not referentially transparent, since they evaluate eagerly and memoize their result. In most use cases, this is totally fine and Scala developers rarely need to create non-evaluated future.
Take the following program:
val x = Future(...); f(x, x)
is not the same program as
f(Future(...), Future(...))
because in the first case the future is evaluated once, in the second case it is evaluated twice.
The are libraries which provide the necessary abstractions to work with referentially transparent asynchronous tasks, whose evaluation is deferred and not memoized unless explicitly required by the developer.
Scalaz Task
Monix Task
fs2
If you are looking to use Cats, Cats effects works nicely with both Monix and fs2.
this is a bit of a hack, since it have nothing to do with how future works but just adding lazy would suffice:
lazy val f = Future { ... // my function}
but note that this is sort of a type change as well, because whenever you reference it you will need to declare the reference as lazy too or it will be executed.