【发布时间】:2013-03-22 06:03:54
【问题描述】:
背景
我想向远程参与者发送一个闭包。远程参与者应该对其数据运行闭包并发回结果。 这可能是不可取的,但出于好奇,我现在想这样做
但我观察到,如果将闭包创建为匿名函数,它也会捕获外部对象并尝试对其进行编组,如果外部对象不可序列化,则会失败,如本例所示。
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))
但这将闭包定义与使用它的地方分开,并违背了使用函数式语言的全部目的。并且也使得定义闭包逻辑更加困难。
具体查询
当我从本地定义的闭包创建MyFunc 的实例时,有没有办法可以推迟定义Function1.apply 的主体并分配apply 的主体?
例如
server ! new Message(new MyFunc(every){ // not valid scala code
x % every == 0
})
every 是一个局部变量?
基本上我想结合这两种方法,即将Function1 的对象发送到远程actor,Function1 的主体由在创建Function1 实例的位置定义的匿名函数定义。
谢谢,
【问题讨论】:
-
我想你知道你在做什么,但我想确保你知道发送闭包被认为是一种不好的做法,正如 documentation - 段落演员最佳实践 alinea 3 中所明确解释的那样跨度>
-
感谢您指出。或者,我可以将该行为封装在一个演员中并动态创建它吗?即根据闭包决定actor的行为,而不是将闭包本身发送给actor。
-
您可以做很多事情,但我感觉您正在尝试针对特定问题实施“错误”/尴尬的解决方案。我相信如果你编辑你的问题并描述你想要达到的目标,你会在 SO 上得到更好的回应
-
好的。我将问题改写为特定查询。如何动态定义
Funtion1[A,B] 's apply()方法的主体?就像我们在实例化接口时如何在 Java 中定义匿名类方法 -
谢谢我刚刚检查了确实可以在创建时定义
Function1的主体。谢谢 :)