Scala - Passing a function to Future.apply - scala

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())

Related

Is this possible in scala def convert(f: () ⇒ Future[Int]): Future[() ⇒ Int] =?

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))
}

Unclear notation in Scala code snippet

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]]

Create Future without starting it

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.

Scala, passing a locally defined function into a list?

I have not understood the following code snippet why afterDelay(0) {...}, a locally defined function can be stored into agenda? Can someone help me understand the afterDelay(0) {...} in the run function?
abstract class Simulation {
type Action = () => Unit
case class WorkItem(time: Int, action: Action)
private var curtime = 0
def currentTime: Int = curtime
private var agenda: List[WorkItem] = List()
private def insert(ag: List[WorkItem], item: WorkItem): List[WorkItem] = {
if (ag.isEmpty || item.time < ag.head.time) item :: ag
else ag.head :: insert(ag.tail, item)
}
def afterDelay(delay: Int)(block: => Unit) {
val item = WorkItem(currentTime + delay, () => block)
agenda = insert(agenda, item)
}
private def next() {
(agenda: #unchecked) match {
case item :: rest =>
agenda = rest
curtime = item.time
item.action()
}
}
def run() {
afterDelay(0) {
println("*** simulation started, time = "+
currentTime +" ***")
}
while (!agenda.isEmpty) next()
}
}
afterDelay(0) {
println(...)
}
Is equivalent to the following:
afterDelay(0)({
println(...)
})
The function afterDelay is invoked a new WorkItem (item) is added to the list, not the function itself. The parameter block: => Unit is a "By-Name Parameter" (see the Scala Language Specification section 4.6.1): the expression used as the argument is implicitly converted into a "parameterless method" (without being evaluated first) that will be invoked whenever the variable inside the method is accessed (no () required).
In this case that is when the function resulting from () => block is invoked: it is invoked at item.action() which occurs at some point after the new WorkItem is added to the list (and afterDelay returns).
If it was written as (taking in a function paramater, not a by-name/thunk):
def afterDelay(delay: Int)(block: () => Unit) { // take a function
// new function will invoke function named by "block" when invoked ...
val item = WorkItem(..., () => block())
// or skip wrapping the function in a function ...
// val item = WorkItem(..., block)
...
}
Then it would need to be invoked passing in a function:
afterDelay(0)(() => { // need a function
println(...)
})
Or, alternative syntax, still a function of () => Unit, but the outside parenthesis can be avoided:
afterDelay(0) { () => // need a function
println(...)
}
Extract from the SLS, 4.6.1 By-Name Parameters:
The type of a value parameter may be prefixed by =>, e.g. x: => T. The type of such a parameter is then the parameterless method type => T. This indicates that the corresponding argument is not evaluated at the point of function application, but instead is evaluated at each use within the function. That is, the argument is evaluated using call-by-name.
You defined afterDelay as a curried function. This means it has two parameter lists. In scala you can replace the brackets surounding the parameterlist (...) with {...}. In the second parameterlist you are using a "call-by-name" parameter. Those parameters are evaluated everytime again you use them in your function. A good Example is here.
"Call-by-name" parameters are often used to define your own controlling structure.
def do(until: Int)(body: => Unit) {
body
if (until > 1) do(until - 1)(body)
}
do(0)(println("test"))
do(5)(println("test2"))
This is an example for a do until. It will print once test and five times test2.

Can you return an unevaluated function in scala?

Given this code:
def getFunc(funcName:String, param:Int) = match funcName {
case "FooFunc" => FooFunc(param)
[...]
}
def FooFunc(param:Int) = param + SomeObject.SomeVariable
How could I return FooFunc with param applied, without evaluating it? The reason I'd want to do this is because FooFunc, as you can see, relies on an external variable so I'd like to be able to call it with param already applied. What would the return type of getFunc need to be?
Easy:
def getFunc(funcName: String, param: Int) = funcName match {
case "FooFunc" => () => FooFunc(param)
[...]
}
Your method has a good name: getFunc is supposed to return a function, so it will.
The lazyness must be defined at the call site, in Scala. You can do:
lazy val x = getFunc(...) // getFunc only gets evaluated when needed
Or you can change the signature:
def FooFunc(param:Int) = () => param + SomeObject.SomeVariable
...
val x = getFunc(...) // x contains a function from Unit into something
x() // Use x here, causing the evaluation
You could add another void parameter, so the function is only evaluated when it is applied to this parameter.
Though I'd rather use a proper object instead of a function in this case.
I'm sure there's many options, but you can use:
return { Unit => FooFun(param) }