Scalaのアクターにケースクラス(case class)を使う方法とその理由らしきものを考えた

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}

https://github.com/RuoAndo/qiita/tree/master/actor/3/HelloActor

25-28行目で、1000ミリ秒(1秒)ごとに「hi」という文字列をアクターに送り続ける。

<pre>
    25    while(true) {
    26      Thread.sleep(1000)
    27      actor ! "hi"
    28    }
</pre>

実行してみる。。。

<pre>
$ 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
</pre>

アクターは「メッセージパッシング」という方法を使っている。。
これは、ある意味、シェイクスピアとかの脚本と同じく、メッセージ（台詞）のみが頼りという事ともとれる。

なので、メッセージにいろいろ（メタな）情報が入るとよい。。

ということにして、ケースクラスを使う。

コードを見てみる。。。

     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}

https://github.com/RuoAndo/qiita/tree/master/actor/2/MyActor

6行目でアクター間でやり取りするケースクラスを定義している。

<pre>
     6case class CaseClass_for_Actor(prop1: Int, prop2: String)
</pre>

27-33行目でメッセージとしてのケースクラスを送信している。

<pre>
    27    val msg = new CaseClass_for_Actor(987654321, "any string")
    28
    29    while(true) {
    30      Thread.sleep(1000)
    31      actor ! msg
    32    }
    33  }
</pre>

実行してみる。。。

<pre>
$ 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
</pre>

（｀ー´）b