What happens in line nine below that makes the result
variable accessible on line ten?
The example is from the Akka documentation on testing. The Ask
in line eight returns a scala.concurrent.Future
. The Future.value()
returns an Option[Try[T]], which will either be Some(Success(t))
or Some(Failure(error))
. Then Some.get
is called, which should either return the t
or the error, depending the result of the Try
.
It seems like whether or not the value of future.value.get
is an error in line nine, it is attempting to instantiate a new Success, which is defined as a case class in Try, with the return value from Some.get
. The Success on line nine is not used directly, but instead the case class constructor parameter result
somehow makes it into scope so it can be used in line ten. What is this called in Scala? Where can I find out more about how this syntax works?
1. import akka.testkit.TestActorRef
2. import scala.concurrent.duration._
3. import scala.concurrent.Await
4. import akka.pattern.ask
5.
6. val actorRef = TestActorRef(newMyActor)
7. // hypothetical message stimulating a '42' answer
8. val future = actorRef ? Say42
9. val Success( result: Int ) = future.value.get
10. result should be (42)
val Success( result: Int ) = future.value.get
is a pattern match. You can use pattern-matching to assign values to identifiers when declaring a val. It's about the same as writing:
val result: Int = future.value.get match {
case Success(r: Int) => r
}
Notice how this is not an exhaustive match, though, and if future.value.get
is a Failure
, then a MatchError
will be thrown. In the context of unit tests, I use pattern matching like this all the time, since a MatchError
would be another indication of failure.
Here are a few examples of similar (safer) pattern-matching assignments:
val (a, b) = (1, 2)
case class Test(i: Int, j: String)
val test = Test(1, "a")
val (i, j) = test
val list = List(1, 2, 3, 4)
val List(first, second, _*) = list // though this will fail if the List has less than 3 elements