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]]
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())
I am new to Scala and am working on an application using akka and futures
I have a class(C) that processes a future and returns a List(L) of objects type X. X has a field y and it is this field I am interesed in. (Note: L was previously converted from a ListBuffer type).
In the Main Class that calls C the code to process the result is:
Snippet A:
result1.onComplete {
result =>
result.foreach(f = (o: List[X]) => {
o.foreach(f = (o: x) => {
println(X.y)
})
})
}
I can also use this code:
Snippet B:
result1 onSuccess{
case result =>
result.foreach(f = (o: X) => {
println(o.y)
})
}
Obviously, as OnSuccess is deprecated the first form may be preferred. The second form (Snippet B) I can understand, but I am baffled as to why, when using onComplete, I have to use nested 'foreach' to get to the same result. If anyone can help as I dont yet have a clear conception of what 'result' (Try[T] => U) ??? actually is. Thanks in advance..:)
If you take a look to the Future.onComplete scaladoc, you will see that it receives a function from Try[T], (where T is the type of your future), to Unit.
"When this future is completed, either through an exception, or a value, apply the provided function".
"Note that the returned value of f will be discarded".
The Try is there to catch failures on the asynchronous computation - that's why you need the two foreach, the first one is to extract the Successful List from the Try, and the second one is to extract each element O from the List.
You didn't need two in the case of onSuccess because, as the name says that callback would only be called if the Future completed successfully.
However, note that doing a foreach on a Try is a bad idea, since you are not handling the failure, also the code become hard to read - try this instead.
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Success, Failure}
case class Result(data: Int)
val process: Future[List[Result]] =
Future.successful(List(Result(data = 5), Result(data = 3)))
process.onComplete {
case Success(results) =>
for (result <- results) {
println(result.data)
}
case Failure(ex) =>
println(s"Error: ${ex.getMessage}")
}
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))
}
Consider the following:
Stream.continually(List(1,2,3)).transpose
You would expect to get something equivalent to:
Stream(
Stream.continually(1),
Stream.continually(2),
Stream.continually(3)
)
However, the upper construct loops infinitely. Is there a workaround for this? Is this to be considered a bug?
Question came up discussing this answer.
EDIT
I know that a function like this writable, see the following example. But is there something in the library?
def myTranspose[A,B](in: Stream[A])
(implicit asTraversable: A => GenTraversableOnce[B]): Stream[Stream[B]] = {
val len = asTraversable(in.head).size
for (i <- (0 until len).toStream)
yield in.map(el => asTraversable(el).toIndexedSeq(i))
}
My assignment is to write a custom repeat control structure that can be used like this:
var i = 0
repeat {
i = i + 1
}(i > 5)
I currently have the following code for that:
def repeat(f: => Unit): ((=> Boolean) => Unit) = {
(x) => {
while (x) f
}
}
When running this, it seems f (i = i + 1) is never executed.
I have to be honest, I'm not entirely sure what the current type of x is. It's clearly not correct, but I don't have enough knowledge to know where to go from here.
I used to have this:
def repeat(f: => Unit): ((=> Boolean) => Void) = {
(x: (=> Boolean)) => {
while (x) f
}
}
Although this is apparently incorrect Scala, I think it demonstrates my intent better.
I'm sorry if my question is a bit broad/demonstrates effortlessness, but the concept of by-name parameters is very new to me and not explained in my book (Programming in Scala) beyond the basics.
You should also be aware that Scala supports multiple parameter lists. So you could
def compare(a: Int, b: Int)(p: (Int,Int) => Boolean) = p(a,b)
and then write
compare(5,2)(_ > _)
This type of strategy will simplify your logic.
Also, you have your comparison backwards. i starts out at 0 and your loop condition is i > 5, which it is not.
A few extra notes: => X means "compute an X each time one is needed", so ((=> Boolean) => Unit) takes something that will compute a Boolean as needed (and i > 5 can do that, if the check is performed each time, which it will be). (=> Boolean) => Unit means a function that takes as input something that produces Booleans and gives no output. (Well, strictly speaking, Unit type is an output, namely (), which is done for consistency. But it serves the same role as void.)