背景
我想向一个远程演员发送一个闭包.远程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)
}
}
Run Code Online (Sandbox Code Playgroud)
上面的代码在调用远程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))
Run Code Online (Sandbox Code Playgroud)
但是这将闭包定义与它所使用的地方分开,并且破坏了使用函数语言的整个目的.并且还使得定义闭包逻辑变得更加困难.
具体查询
当我从本地定义的闭包创建实例时,有没有一种方法可以推迟定义主体Function1.apply并分配主体?applyMyFunc
例如
server ! new Message(new MyFunc(every){ // not valid scala code
x % every == 0
})
Run Code Online (Sandbox Code Playgroud)
哪里every是局部变量?
基本上我想要结合这两种方法,即将一个对象发送Function1到远程actor,其主体Function1由在Function1创建实例的地方定义的anon函数定义.
谢谢,
当然,您可以将行为发送给演员,但这被认为是一种不好的做法,并且您的问题是“为什么”问题的一个很好的答案。
正如 BGR 指出的那样,文档中有关于此问题的特殊部分,但没有示例。
因此,当您将闭包作为消息发送时,您会发送一些额外的“隐式”状态。正如文档中所述,它可能是不可变的,但即使在这种情况下,它也会产生问题。
scala 的问题在于它不是严格的函数式语言——它是多范式语言。换句话说,您可以将函数式范例中的代码与命令式风格的代码并排放置。例如haskell就不存在这样的问题,它是纯函数式的。
如果您有“特定查询”,我建议您使用一组预定义函数。这与带有闭包的变体完全等效,但语法有点啰嗦。由于您在运行时不会生成代码,因此您使用的所有函数都是在有限集中定义的,并且(看起来)按值参数化。这使得你的代码不像闭包那样灵活,但最终它会是等效的情况。
因此,作为我所有帖子的主题:如果您要将行为发送给演员,它应该是坚如磐石的原子(意味着没有任何依赖性)
| 归档时间: |
|
| 查看次数: |
1952 次 |
| 最近记录: |