Akkaのreceiveと
Scala・Javaの違い
前多賢太郎 @kencharos
内容
 自己紹介
 Akka の receive は何?
 部分関数とは
 Akka (Java)のreceiveについて
自己紹介
 前多賢太郎 (@kencharos)
 ウルシステムズ株式会社所属
 Javaプログラマー
 最近の仕事
 Spring(boot)のアプリケーション構築・教育
 Playframework(Java) + Cassandra 案件の技術コンサル
 好きなAWSサービス: Lambda
 仕事以外
 Scala 独学中
 akka-doc-jaに参加中(みなさんもぜひ)
 https://github.com/akka-ja/akka-doc-ja
akka の receive を見たとき
 俺の知ってる 関数の定義と何か違う
 いきなり始まる case とパターンマッチ
 メッセージを処理する関数なのに引数は? 戻り値は?
 パターンマッチに該当しない場合の処理は?
// Actor#receive
def receive = {
case "ping" => {
sender ! "pong"
}
}
// 普通の関数
def func(x:String) = {
"Hello" + x
}
def receive の定義
 receiveは Receive型の戻り値を返す引数なしの抽象メソッド
 Receive型は, PartialFunction[Any, Unit] 型のエイリアス
 つまり、 receiveの中身は、PartialFunction の定義
 PartialFunction?
def receive: Actor.Receive
type Receive = PartialFunction[Any, Unit]
PartialFunction(部分関数) とは?
 特定の引数について任意の処理を行うオブジェクト
 特定の引数と処理の組を、パターンマッチの一覧で定義
できる
 通常の関数のように呼び出せるが、マッチしない引数だ
とエラー
def pfSample:PartialFunction[String, Unit] = {
case "John" => println("hello Jhon")
case "Tony" => println("Get out! Tony")
}
pfSample("Jhon") // "hello!"
pfSample("Tony") // "get out!"
pfSample("Michel") // 実行時エラー
PartialFunctionの便利機能
 マッチしない引数の確認やデフォルト処理を設定できる
 Akka の場合、 applyOrElse で、receiveで処理できないメッ
セージをunhandled メソッドで処理している
 unhandledを通して、アクターの終了検知やデッドレター送付など共通処
理を行っている
if (pfSample.isDefinedAt("Michel")) {
pfSample("Michel")
} else {
"strange!"
}
pfSample.applyOrElse("Michel",
(name:String) => s"${name} is stranger!")
protected[akka] def aroundReceive(receive: Actor.Receive, msg: Any): Unit =
receive.applyOrElse(msg, unhandled)
PartialFunctionであることを生かす
 PartialFunctionは合成できる
 各アクターを横断して行うメッセージの処理を traitなどで
定義して、各アクターのreceiveに合成できる
 詳しくは↓
http://doc.akka.io/docs/akka/current/scala/actors.html#Extendi
ng_Actors_using_PartialFunction_chaining
trait CommonProcess {
this: Actor =>
val greeting :Receive = {
case "Greeting" =>
sender ! s"Hello! I am ${self.path.name}"
}
}
class SomeActor extends Actor with CommonProcess{
def receive = greeting orElse {
case "ping" => {
sender ! "pong"
}
}
}
Java版だとどうなの?
Java の場合 unhandledを自分で呼ぶ
 Java(UntypedActor)の場合、unhandledの明示的な呼び出
しが必要
 Scalaと同じように書けなくてつらい
 でもAkkaでunhandledを呼ばせるには、メッセージ判定と
メッセージ処理の2つの抽象メソッドをほぼ同じ内容で定
義する必要がある
@Override
public void onReceive(Object message) throws Exception {
if ((message instanceof String) && ((String)message).equals("Ping")) {
getSender().tell("Pong", getSelf());
} else {
unhandled(message);
}
}
将来的には改善されるかも?
 lambda support (experimental) で、パターンマッチ相当
の機能が提供されるかも
 http://doc.akka.io/docs/akka/current/java/lambda-actors.html
まとめ
 Akka (Scala) は Scala の文法や機能を駆使して、書き易
いAPI を提供している
 パターンマッチ、PartialFunction、Implicit parameter, traitなど
 Akka (Java) もがんばってはいるが、型推論とパターン
マッチがないと書いていてつらい
 unhandledの明示も抜けを防ぐ仕組みが無いのでつらい
 私見だがScala・Java を使い分けるなら次のような感じ
 全面的に Akka を採用するアプリケーション => Scala
 既存Javaシステムの一部にAkka を組み込む => Java

【LT】akka receive とScala Javaの違い

  • 1.
  • 2.
    内容  自己紹介  Akkaの receive は何?  部分関数とは  Akka (Java)のreceiveについて
  • 3.
    自己紹介  前多賢太郎 (@kencharos) ウルシステムズ株式会社所属  Javaプログラマー  最近の仕事  Spring(boot)のアプリケーション構築・教育  Playframework(Java) + Cassandra 案件の技術コンサル  好きなAWSサービス: Lambda  仕事以外  Scala 独学中  akka-doc-jaに参加中(みなさんもぜひ)  https://github.com/akka-ja/akka-doc-ja
  • 4.
    akka の receiveを見たとき  俺の知ってる 関数の定義と何か違う  いきなり始まる case とパターンマッチ  メッセージを処理する関数なのに引数は? 戻り値は?  パターンマッチに該当しない場合の処理は? // Actor#receive def receive = { case "ping" => { sender ! "pong" } } // 普通の関数 def func(x:String) = { "Hello" + x }
  • 5.
    def receive の定義 receiveは Receive型の戻り値を返す引数なしの抽象メソッド  Receive型は, PartialFunction[Any, Unit] 型のエイリアス  つまり、 receiveの中身は、PartialFunction の定義  PartialFunction? def receive: Actor.Receive type Receive = PartialFunction[Any, Unit]
  • 6.
    PartialFunction(部分関数) とは?  特定の引数について任意の処理を行うオブジェクト 特定の引数と処理の組を、パターンマッチの一覧で定義 できる  通常の関数のように呼び出せるが、マッチしない引数だ とエラー def pfSample:PartialFunction[String, Unit] = { case "John" => println("hello Jhon") case "Tony" => println("Get out! Tony") } pfSample("Jhon") // "hello!" pfSample("Tony") // "get out!" pfSample("Michel") // 実行時エラー
  • 7.
    PartialFunctionの便利機能  マッチしない引数の確認やデフォルト処理を設定できる  Akkaの場合、 applyOrElse で、receiveで処理できないメッ セージをunhandled メソッドで処理している  unhandledを通して、アクターの終了検知やデッドレター送付など共通処 理を行っている if (pfSample.isDefinedAt("Michel")) { pfSample("Michel") } else { "strange!" } pfSample.applyOrElse("Michel", (name:String) => s"${name} is stranger!") protected[akka] def aroundReceive(receive: Actor.Receive, msg: Any): Unit = receive.applyOrElse(msg, unhandled)
  • 8.
    PartialFunctionであることを生かす  PartialFunctionは合成できる  各アクターを横断して行うメッセージの処理をtraitなどで 定義して、各アクターのreceiveに合成できる  詳しくは↓ http://doc.akka.io/docs/akka/current/scala/actors.html#Extendi ng_Actors_using_PartialFunction_chaining trait CommonProcess { this: Actor => val greeting :Receive = { case "Greeting" => sender ! s"Hello! I am ${self.path.name}" } } class SomeActor extends Actor with CommonProcess{ def receive = greeting orElse { case "ping" => { sender ! "pong" } } }
  • 9.
  • 10.
    Java の場合 unhandledを自分で呼ぶ Java(UntypedActor)の場合、unhandledの明示的な呼び出 しが必要  Scalaと同じように書けなくてつらい  でもAkkaでunhandledを呼ばせるには、メッセージ判定と メッセージ処理の2つの抽象メソッドをほぼ同じ内容で定 義する必要がある @Override public void onReceive(Object message) throws Exception { if ((message instanceof String) && ((String)message).equals("Ping")) { getSender().tell("Pong", getSelf()); } else { unhandled(message); } }
  • 11.
    将来的には改善されるかも?  lambda support(experimental) で、パターンマッチ相当 の機能が提供されるかも  http://doc.akka.io/docs/akka/current/java/lambda-actors.html
  • 12.
    まとめ  Akka (Scala)は Scala の文法や機能を駆使して、書き易 いAPI を提供している  パターンマッチ、PartialFunction、Implicit parameter, traitなど  Akka (Java) もがんばってはいるが、型推論とパターン マッチがないと書いていてつらい  unhandledの明示も抜けを防ぐ仕組みが無いのでつらい  私見だがScala・Java を使い分けるなら次のような感じ  全面的に Akka を採用するアプリケーション => Scala  既存Javaシステムの一部にAkka を組み込む => Java

Editor's Notes

  • #11 Instanceof は割愛