7

バックグラウンド

リモートアクターにクロージャーを送信したい。リモートアクターは、そのデータに対してクロージャーを実行し、結果を送り返す必要があります。 お勧めできないかもしれませんが、好奇心のために今やりたいことです

しかし、クロージャが無名関数として作成された場合、外部オブジェクトもキャプチャしてマーシャリングしようとしますが、この場合のように、外部オブジェクトがシリアル化できない場合は失敗します。

class Client(server: ActorRef) extends Actor {

  var every = 2

  override def preStart() = {
    println("client started. sending message....")
    server ! new Message((x) => x % every == 0)
  }

}

上記のコードは、リモートアクターの呼び出し中に例外を生成します。メソッドでローカル変数を定義できますpreStart()

val every_ = every

アクターメンバー変数の代わりに使用します。しかし、それは解決策ではなく回避策だと思います。クロージャーがもう少し複雑な場合は、非常に注意する必要があります。

別の方法は、インスタンスを継承してクラスを定義し、Function1[A,B]そのインスタンスをクロージャーとして送信することです。

class MyFunc(every : Int) extends Function1[Int,Boolean] with Serializable {

  def apply(v1 :Int) : Boolean = {
    v1 % every == 0
  }  
}


server ! new Message(new MyFunc(every))

しかし、これはクロージャーの定義をそれが使用される場所から分離し、関数型言語を使用するという目的全体を無効にします。また、クロージャロジックの定義がより困難になります。

特定のクエリ

ローカルで定義されたクロージャからのインスタンスを作成するときに、の本体の定義を延期し、の本体Function1.applyを割り当てる方法はありますか?applyMyFunc

例えば

server ! new Message(new MyFunc(every){ // not valid scala code
  x % every == 0
})

everyローカル変数はどこにありますか?

基本的に、2つのアプローチを組み合わせたいと思います。つまり、インスタンスが作成される場所で定義されたanon関数によって定義されたFunction1本体を使用して、リモートアクターにoverのオブジェクトを送信します。Function1Function1

ありがとう、

4

1 に答える 1