7

背景

我想向远程演员发送闭包。远程参与者应该对其数据运行闭包并发回结果。 可能是不可取的,但出于好奇,这就是我现在想做的

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

class Client(server: ActorRef) extends Actor {

  var every = 2

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

}

上面的代码在调用远程参与者时会产生异常。我可以在方法中定义一个局部变量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并分配主体?applyMyFunc

例如

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

every局部变量在哪里?

基本上我想结合这两种方法,即将一个对象发送Function1到远程参与者,其主体由在创建实例Function1的地方定义的匿名函数定义。Function1

谢谢,

4

1 回答 1

4

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

正如 BGR 指出的那样,文档中有关于此问题的特殊部分,但没有示例。

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

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

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

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

于 2013-10-29T18:03:07.440 回答