akka向远程演员发送封闭

时间:2013-03-22 06:03:55

标签: scala akka actor

背景

我想向远程actor发送一个闭包。远程actor应该对其数据运行闭包并发回结果。 可能是不可取的,但出于好奇,我现在想做的事

但是我观察到如果一个闭包被创建为一个匿名函数,它也会捕获外部对象并尝试编组它,如果外部对象不可序列化则会失败,就像在这种情况下一样。

class Client(server: ActorRef) extends Actor {

  var every = 2

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

}

上面的代码在调用远程actor时生成异常。我可以在方法preStart()

中定义一个局部变量

val every_ = every

并使用它代替actor成员变量。但我觉得这是一种解决方法而不是解决方案。如果封闭更复杂,我必须非常小心。

替代方法是定义一个继承自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的实例时,有没有办法可以推迟定义apply的主体并分配MyFunc的主体?

e.g。

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

其中every是一个局部变量?

基本上我想要结合两种方法,即将Function1的对象发送到远程actor,其中Function1的主体由定义的anon函数定义,其中Function1实例是创建

谢谢,

1 个答案:

答案 0 :(得分:4)

当然,你可以向演员发送行为,但这被认为是一种不好的做法,你的问题是一个很好的答案:“为什么”。

正如BGR所指出的,documentation中有关于这个问题的特殊部分,但它没有例子。

因此,当您发送一个闭包作为消息时,您会发送一些额外的“隐式”状态。它可能不像文档中所说的那样是可变的,但即使在这种情况下它也会产生问题。

scala的问题在于它不是严格的函数式语言 - 它是多范式语言。换句话说,您可以在功能范例中将代码与命令式样式中的代码并排放置。没有这样的问题,例如haskell,它纯粹是功能性的。

如果您的“特定查询”,我建议您使用一组预定义的功能。这完全等同于带闭包的变体,但语法有点繁琐。由于您在运行期间不生成代码,因此您使用的所有函数都在有限集中定义,并且(看起来像)按值参数化。这使得您的代码不像闭包那样灵活,但最终它将是等效的情况。

所以,作为我所有帖子的主题:如果你要向演员发送行为,它应该是坚如磐石的原子(意思是没有任何依赖)