2013-03-22 58 views
6

背景阿卡发送关闭远程演员

我想封闭发送到远程的演员。远程参与者应该对其数据运行关闭并发回结果。 可能这是不可取的,但为了好奇这就是我想做的事情现在

但我观察,如果一个封闭作为一个匿名函数创建的,它抓住了外部对象也并试图封送它,这如果外部对象不可序列化,则失败,如在这种情况下。

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

定义本地变量和到位的演员成员变量的使用它。但我觉得这是一种解决方法,而不是解决方案。如果封闭更复杂,我将必须非常小心。

另一种方法是定义继承自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的身体,当我从一个本地定义封闭创建MyFunc的实例分配的apply的身体吗?

例如

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

where every是一个局部变量?

基本上我希望将两种方法结合起来,即发送的Function1对象到远程演员与Function1通过在其中创建Function1实例地方定义一个匿名函数所定义的身体。

感谢,

+0

我想你知道你在做什么,但我想以确保你知道发送关闭被认为是一个不好的做法,正如[文档](http://doc.akka.io/docs/akka/snapshot/general/actor-systems.html)中明确解释的那样 - Actor最佳实践alinea 3 – 2013-03-22 06:10:19

+0

感谢您指出。或者我可以将这种行为封装在actor中并动态创建它?即基于闭包来决定演员的行为,而不是将闭包本身发送给演员。 – weima 2013-03-22 06:15:45

+0

有很多你可以做的,但我有一种感觉,你正试图实现对特定问题的“错误”/尴尬的解决方案。我相信如果你编辑你的问题并描述你想达到的目标,你会在SO – 2013-03-22 06:26:01

回答

3

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

由于BGR指出在这个问题上有documentation特殊部分,但它没有例子。

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

这里scala的问题在于它没有严格的功能语言 - 它是多种语言的语言。换句话说,你可以在功能范式中使用命令式风格的代码。没有这样的问题,例如haskell,这是纯粹的功能。

如果您的“具体查询”,我会建议您使用一组预定义的功能。这完全相当于带有闭包的变体,但有一些简洁的语法。由于您在运行时不生成代码,因此您使用的所有函数都是在有限集内定义的,并且(看起来像)按值进行参数化。这使得你的代码不像闭包一样灵活,但最终它会成为等价的情况。

所以,我的所有文章的中心思想:如果你要发送行为的演员应该是稳如磐石的原子(在意义上没有任何依赖关系)