Reputation: 27373
I recently looked into scala multithreading tutorials and stumbled on a method which is implemented in an Actor:
class MyActor extends Actor
def receive = {
case "test" => println("received test")
case _ => println("received unknown message")
}
}
Although I think I know what the method does, I can't figure out how to use such a method (at it does not take any arguments).
Althouh the example is about Akka, I think this is unrelated to Akka
Upvotes: 2
Views: 352
Reputation: 14217
As @Fatih Donmez said, it's a Parital Funciton, this defined certain values of certain types, usage:
List("hello", "test").foreach {
case "test" => println("received test")
case _ => println("received unknown message")
}
(0 to 20) collect {
case i if i % 2 == 0 => i
}
(0 to 20) map {
case i if i % 2 == 0 => i * i
case j => j
}
also you can use it directly, like:
val f1: PartialFunction[Int, Unit] = {
case 1 => println("I am 1")
case t => println(s"I am $t")
}
f1(1)
> I am 1
f1(2)
> I am 2
orElse Example:
val f1: PartialFunction[Int, Int] = {
case i if i % 2 == 0 => i * i
}
val f2: PartialFunction[Int, Int] = {
case i if i % 2 != 0 => i+1
}
val f = f1 orElse f2
f(1)
> 2
(0 to 10) map f
> scala.collection.immutable.IndexedSeq[Int] = Vector(0, 2, 4, 4, 16, 6, 36, 8, 64, 10, 100)
andThen Example:
val f1: PartialFunction[Int, Int] = {
case i if i % 2 == 0 => i * i
case j => j
}
val f2: PartialFunction[Int, Int] = {
case i if i % 2 != 0 => i * i
case j => j + 1
}
val f = f1 andThen f2
f(2)
res20: Int = 5
(0 to 10) map f
> scala.collection.immutable.IndexedSeq[Int] = Vector(1, 1, 5, 9, 17, 25, 37, 49, 65, 81, 101)
compose Example:
val f1: PartialFunction[Int, Int] = {
case i if i % 2 == 0 => i * i
case j => j
}
val f2: PartialFunction[Int, Int] = {
case i if i % 2 != 0 => i * i
case j => j + 1
}
val f = f1 compose f2
f(2)
res18: Int = 3
(0 to 10) map f
res17: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 1, 3, 9, 5, 25, 7, 49, 9, 81, 11)
docs:
Upvotes: 1
Reputation: 4347
Actually receive
returns partial function. When you check the source code of Actor
you'll see that;
type Receive = PartialFunction[Any, Unit]
So it means with overriding receive you're providing a partial function which takes any parameter and return unit. At some point later, if your actor gets a message Akka itself will use this partial function to do pattern match over the incoming message.
-- Edit --
For more concrete example, let say you created a similar object;
object Obj {
def receive: PartialFunction[Any, Unit] = {
case "test" => println("test case")
case 1 => println("int 1 case")
case d: Double => println("double case $d")
case _ => println("rest")
}
}
Then you can call this partial function like regular method call;
scala> Obj.receive(1)
int 1 case
scala> Obj.receive("test")
test case
Actor case is specific, it's just that you don't call the receive directly, you provide it and Akka itself calls it if the messages arrive;
protected[akka] def aroundReceive(receive: Actor.Receive, msg: Any): Unit = receive.applyOrElse(msg, unhandled)
Of course this call depends on lots of parameters like the topology you use,mailbox and etc.
Upvotes: 7