Future mapping transparently split in two functions when using anonymous parameters

future, scala

Solution

It may surprize you, but println is executed during lambda construction time:

List(1,2,3).map { 
    println("Hi!")
    "Processing " + _ 
}

// Hi! 
// res4: List[String] = List(Processing 1, Processing 2, Processing 3)

As you can see `Hi!` is outputed only once.

That is because your code is semantically identical to:

def constructLambda() = {
  // do something, e.g. println
  // now return actual lambda
}
val lambda = constructLambda()
xs map (lambda) // now trigger previously *lazy* piece of code
// or even this, like in your snippet
xs map lambda

Problem

I am stuck with something I observed with Scala futures and I cannot figure out what happens here. I am mapping a future to another result, nothing fancy here: ``` import scala.concurrent.{Await, Future} import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.duration._ object Example extends App { val f = Future { Thread.sleep(1000) println("Future: " + Thread.currentThread + " (" + System.currentTimeMillis + ")") "future" } val g = f map { x => println("Map future: " + Thread.currentThread + " (" + System.currentTimeMillis + ")") "mapped " + x } println(Await.result(g, 5 seconds)) } ``` Since the function I map the future to is depending on the result of `f`, I expect the function to be only triggered after the computation of `f` is complete. This is also what I can observe with the above code. However, when I change the function for `g` to carry anonymous parameters, this behavior changes: ``` val g = f map { println("Map future: " + Thread.currentThread + " (" + System.currentTimeMillis + ")") "mapped " + _ } ``` Even though the result of `g` depends on the result of `f`, the method is triggered before the computation of `f` completes. It seems as if the method is split to a part before and after the input value is actually required. Also, the first part of the thread is executed in main. Is this the compiler that does something fancy here? For me, this comes pretty unexpected. Or is this behavior expressed somewhere in Scala? I could not find it in the sources, though. Anybody knows what is going on here? I am using Scala 2.10.

Original source