The problem here is not of scoping but of timing.
- First you're initializing
ret
toNone
. - Then you're sending the message
arg
tosomeActor
, which returns a future. - After that, you set up a function to be called when the future completes, which, if all goes well, will assign a value of 1 or 2 to
ret
at some point in the future. - Last of all, you immediately return the value of
ret
, which is stillNone
. - And at some point in the future, the future completes, and your onSuccess function runs changing the value of
ret
and then printing it. But of course that can't go back in time and change the value that was already returned earlier.
So, to answer your question, there is nothing you can do in the onSuccess that will go back in time and change the already returned value. There are two alternatives though. One alternative would be to block until the future completes, then determine whether to return 1 or 2. The other is to return a Future[Int]
so the caller can decide whether or not they want to block on the result. The code for that is actually simpler than what you have:
def futureFunction(arg:Any):Future[Int] = {
implicit val timeout = Timeout(10 seconds)
val f: Future[Any] = someActor ? arg
f.map {
case a:String => 1
case a:Int => 2
}
}
If you do need to block, you can use Await.result
, either inside or outside futureFunction depending on where you want to block.