Akka sends closure to remote actor

Background

I want to send a close to a remote actor. the remote actor must start closing its data and send the result. It may not be practical, but for the sake of curiosity, what I want to do now

But I notice that if the closure is created as an anonymous function, it also captures the external object and tries to marshal it, which fails if the external object is not serialized, as in this case.

class Client(server: ActorRef) extends Actor { var every = 2 override def preStart() = { println("client started. sending message....") server ! new Message((x) => x % every == 0) } } 

the above code throws an exception when calling a remote member. I could define a local variable in the preStart() method

val every_ = every

and use it instead of an actor member variable. But I believe that this is not a solution. and I have to be very careful if closing is a little tricky.

An alternative is to define a class that inherits from Function1[A,B] and send its instances as a closure.

 class MyFunc(every : Int) extends Function1[Int,Boolean] with Serializable { def apply(v1 :Int) : Boolean = { v1 % every == 0 } } server ! new Message(new MyFunc(every)) 

But this separates the definition of closure from the place in which it is used, and defeats the whole purpose of using a functional language. and also makes it difficult to determine closure logic.

Specific request

Is there a way to defer the definition of the Function1.apply body and assign the apply body when I create an instance of MyFunc from a locally defined closure?

eg.

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

where every is a local variable?

Basically, I want to combine the two approaches, that is, send a Function1 object to a remote actor with the body Function1 defined by the anon function defined at the place where the Function1 instance was created.

Thanks,

+6
source share
1 answer

Of course, you can send behavior to an actor, but it is considered bad practice, and your questions are a good answer to the question β€œwhy.”

As BGR pointed out, there is a special section in the documentation for this question, but there is no example in it.

So, when you send a closure as a message, you send it some kind of extra β€œimplicit” state. It may not be changed as indicated in the documentation, but even then it can cause problems.

The problem with scala is that it is not a strictly functional language - it is a multi-paradigm language. In other words, you can have code in a functional paradigm side by side with code in an imperative style. There is no such problem, for example, haskell, which is purely functional.

In the case of your "specific request", I suggest you use a set of predefined functions. This is the full equivalent of the closure option, but with a bit of chatty syntax. Since you are not generating code at runtime, all the functions you use are determined by a limited set and (looks) parameterized by value. This does not make your code as flexible as when closing it, but in the end it will be equivalent cases.

So, as the leitmotif of my entire post: if you are going to send behavior to an actor, it must be a solid atom (meaning it has no dependencies)

+3
source

All Articles