How does pattern matching work in Akka.Actor method?
I am new to Scala programming and do not understand how actors work and how to use them correctly.
Looking at the source code of Akka Akka , the following is shown:
trait Actor {
def receive: Actor.Receive // Actor.Receive = PartialFunction[Any, Unit]
}
My first impression of this is that an Actor is a trait that provides one abstract method receive
, that takes no arguments, and then returns a partial function. The first question is, is this the correct interpretation of the API?
Then I went through the documentation on how to implement members. Examples look something like this:
class HelloActor extends Actor {
def receive = {
case "hello" => println("hello back at you")
case _ => println("huh?")
}
}
Clearly there is some pattern matching going on here, but I am having a hard time understanding how it works. For example, let's say I wanted to call the receive method directly, without using something like send
, how would I do it?
as others have already answered, you should never directly call methods on Actors. But your question seems to be more about "how does PartialFunction work in Scala?", Right?
Scala PartialFunction[In, Out]
has a bit of compiler-generated code for methods such as isDefinedAt
, so you can define a partial function if it is defined for a specific argument:
scala> val fun: PartialFunction[Any, String] = {
| case 42 => "yes"
| }
fun: PartialFunction[Any,String] = <function1>
scala> fun.isDefinedAt(12)
res0: Boolean = false
scala> fun.isDefinedAt(42)
res1: Boolean = true
scala> fun(42)
res2: String = yes
scala> fun(12)
scala.MatchError: 12 (of class java.lang.Integer)
``,
We use a method isDefinedAt
before we apply the message to the function receive
, and if it fails to process the message, we pass it to unhandled(msg)
, which usually just writes the message in dead letters so you can understand that your Actor hasn't processed the message.
For example, let's say that I wanted to call the receive method directly without using something like send, how would I do that?
You wouldn't do that.
Calling an receive
actor function directly without going through it ActorRef
violates the guarantees of the actor model:
- Actors process exactly one message at a time.
- The internal state of an actor can only be mutated from the receive function.
(among others, see What is an actor? )
When you send a message ActorRef
, you are not directly talking to the actor. Hidden behind ActorRef
is any number of implementation details - you can send a message to a router or a remote player or a dead actor (or all three!). Isolating the details of the actor behind this link ensures that these are all points in the actor's model.