ScalaにActor アクターという仕組みがある。
アクター間でメッセージをやり取りするのだが、Scalaではこのメッセージに文字列だけではなくケースクラスを使うことができる。
ケースクラスは、(おそらく)Scala固有のものである。アクターではケースクラスを使うことが多く、おそらく、これがアクターの敷居を少し上げているのだろう。。
個人的には、ケースクラスは、パターンマッチにだけ使うのだろうと、かたくなに思い込んでいたので、これでハマった。
(*´Д`)
文字列を使ったアクターを見てみる。。。
1import akka.actor.ActorSystem
2import akka.actor.Props
3import akka.actor.Actor
4import akka.event.Logging
5
6class Actor_with_String extends Actor {
7 val log = Logging(context.system, this)
8
9 def receive = {
10 case s: String => {
11 log.info(s)
12 }
13 case _ => {
14 }
15 }
16}
17
18object Main {
19 def main(args: Array[String]): Unit = {
20 val system = ActorSystem("mySystem")
21
22 val props = Props[Actor_with_String]
23 val actor = system.actorOf(props, name = "myActor")
24
25 while(true) {
26 Thread.sleep(1000)
27 actor ! "hi"
28 }
29 }
30}
25-28行目で、1000ミリ秒(1秒)ごとに「hi」という文字列をアクターに送り続ける。
25 while(true) {
26 Thread.sleep(1000)
27 actor ! "hi"
28 }
実行してみる。。。
$ sbt run
[info] welcome to sbt 1.4.1 (Private Build Java 1.8.0_275)
[info] loading project definition from /home/flare/qiita/actor/3/HelloActor/project
[info] loading settings for project helloactor from build.sbt ...
[info] set current project to helloactor (in build file:/home/flare/qiita/actor/3/HelloActor/)
[info] running Main
[INFO] [11/15/2020 19:10:08.974] [mySystem-akka.actor.default-dispatcher-2] [akka://mySystem/user/myActor] hi
[INFO] [11/15/2020 19:10:09.972] [mySystem-akka.actor.default-dispatcher-3] [akka://mySystem/user/myActor] hi
アクターは「メッセージパッシング」という方法を使っている。。
これは、ある意味、シェイクスピアとかの脚本と同じく、メッセージ(台詞)のみが頼りという事ともとれる。
なので、メッセージにいろいろ(メタな)情報が入るとよい。。
ということにして、ケースクラスを使う。
コードを見てみる。。。
1import akka.actor.ActorSystem
2import akka.actor.Props
3import akka.actor.Actor
4import akka.event.Logging
5
6case class CaseClass_for_Actor(prop1: Int, prop2: String)
7
8class Actor_with_CaseClass extends Actor {
9 val log = Logging(context.system, this)
10
11 def receive = {
12 case CaseClass_for_Actor(prop1, prop2) => {
13 log.info("prop1: %d, prop2: %s" format (prop1, prop2))
14 }
15 case _ => {
16 }
17 }
18}
19
20object Main {
21 def main(args: Array[String]): Unit = {
22 val system = ActorSystem("mySystem")
23
24 val props = Props[Actor_with_CaseClass]
25 val actor = system.actorOf(props, name = "myActor")
26
27 val msg = new CaseClass_for_Actor(987654321, "any string")
28
29 while(true) {
30 Thread.sleep(1000)
31 actor ! msg
32 }
33 }
34}
6行目でアクター間でやり取りするケースクラスを定義している。
6case class CaseClass_for_Actor(prop1: Int, prop2: String)
27-33行目でメッセージとしてのケースクラスを送信している。
27 val msg = new CaseClass_for_Actor(987654321, "any string")
28
29 while(true) {
30 Thread.sleep(1000)
31 actor ! msg
32 }
33 }
実行してみる。。。
$ sbt run
[info] welcome to sbt 1.4.1 (Private Build Java 1.8.0_275)
[info] loading project definition from /home/flare/qiita/actor/2/MyActor/project
[info] loading settings for project myactor from build.sbt ...
[info] set current project to myactor (in build file:/home/flare/qiita/actor/2/MyActor/)
[info] running Main
[INFO] [11/15/2020 19:28:11.041] [mySystem-akka.actor.default-dispatcher-3] [akka://mySystem/user/myActor] prop1: 987654321, prop2: any string
[INFO] [11/15/2020 19:28:12.039] [mySystem-akka.actor.default-dispatcher-2] [akka://mySystem/user/myActor] prop1: 987654321, prop2: any string
(`ー´)b