背景
我想向远程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
实例是创建
谢谢,
答案 0 :(得分:4)
当然,你可以向演员发送行为,但这被认为是一种不好的做法,你的问题是一个很好的答案:“为什么”。
正如BGR所指出的,documentation中有关于这个问题的特殊部分,但它没有例子。
因此,当您发送一个闭包作为消息时,您会发送一些额外的“隐式”状态。它可能不像文档中所说的那样是可变的,但即使在这种情况下它也会产生问题。
scala的问题在于它不是严格的函数式语言 - 它是多范式语言。换句话说,您可以在功能范例中将代码与命令式样式中的代码并排放置。没有这样的问题,例如haskell,它纯粹是功能性的。
如果您的“特定查询”,我建议您使用一组预定义的功能。这完全等同于带闭包的变体,但语法有点繁琐。由于您在运行期间不生成代码,因此您使用的所有函数都在有限集中定义,并且(看起来像)按值参数化。这使得您的代码不像闭包那样灵活,但最终它将是等效的情况。
所以,作为我所有帖子的主题:如果你要向演员发送行为,它应该是坚如磐石的原子(意思是没有任何依赖)