在没有var的actors中Scala保持状态

在没有var的actors中Scala保持状态,scala,actor,Scala,Actor,在另一种语言中,我使用新状态来维护它,但我不知道如何使用scala actors来实现这一点。我会这样设想: def act(state) react { case blah => act(doSomething(state, blah)) } } 嗯。。有趣的事。我稍微调整了一下我的问题,发现它可以编译。我意识到所发生的一切就是我必须返回一个部分函数。我可以返回一个部分函数,其中有一个参数,所以 import scala.actors._ object MyActor

在另一种语言中,我使用新状态来维护它,但我不知道如何使用scala actors来实现这一点。我会这样设想:

def act(state)
  react {
    case blah => act(doSomething(state, blah))
  }
}

嗯。。有趣的事。我稍微调整了一下我的问题,发现它可以编译。我意识到所发生的一切就是我必须返回一个部分函数。我可以返回一个部分函数,其中有一个参数,所以

import scala.actors._

object MyActor extends Actor {
  def proc(s: Int) {
    react {
      case input: String =>
        if ((s % 10000) == 0) {
          println(s + ", " + input)
        }
        proc(s + 1)
    }
  }

  def act = proc(0)
}

object TestActors {
  def main(args: Array[String]): Unit = {
    MyActor.start()

    for (s <- 1 to 10000000) {
      MyActor ! "a message"
    }
  }
}
导入scala.actors_
对象MyActor扩展了Actor{
def程序(s:Int){
反应{
案例输入:字符串=>
如果((s%10000)==0){
打印项次(s+,“+输入)
}
过程(s+1)
}
}
def act=proc(0)
}
对象测试者{
def main(参数:数组[字符串]):单位={
MyActor.start()

对于(s,还有两种方法可以在不使用vars的情况下将状态存储在actor中。如果您只需要向前传递状态,则可以让actor向自己发送消息:

object MailsSelf {
  import scala.actors._
  class Selfish extends Reactor[Any] {
    def act() { loop { react {
      case i: Int if (i>=0) =>
        println(i)
        this ! (i-1)  // Self-messaging instead of recursive call
      case _ => exit
    }}}
  }
  def main(args: Array[String]) {
    (new Selfish).start() ! 5
  }
}
或者,如果您需要保存在其他消息期间可访问的状态,则可以创建另一个参与者;然后需要通知给您打电话的人有关新参与者的信息:

object EndlessActors {
  import scala.actors._
  class Delegater(n: Int) extends ReplyReactor {
    def act() { loop { react {
      case i: Int if (i*n >= 0) =>
        println(i*n)
        val next = new Delegater(n-1)
        next.start()
        reply(Some(next))
      case _ => reply(None); exit
    }}}
  }
  def main(args: Array[String]) {
    val original = new Delegater(5)
    original.start()
    Iterator.iterate( Option(original) ){ maybe =>
      maybe.flatMap(d => {
        val result = (d !? 5)
        result match {
          case Some(d2: Delegater) => Some(d2)
          case _ => None
        }
      })
    }.takeWhile(_.isDefined).foreach(_ => {})  // Foreach forces evaluation
  }
}

就我个人而言,我认为这样做是愚蠢的。这样做效率很低(当状态发生变化时,必须创建一个新的参与者,并处理一个旧的参与者——而参与者并不是那么轻量级!),而且这会使代码大大复杂化。在大多数情况下,将可变状态安全地隐藏为
private[this]var
,这样您就知道只有参与者本身可以更改其可变状态。或者,您可以不使用新的参与者,而是使用调用者应该传回的状态信息进行回复,但这稍微不那么安全,因为原则上,他们可以修改状态信息,而不只是传回同样。

在这种情况下,明智的做法是将@tailrec注释添加到proc方法()。以确保您没有炸毁堆栈。谢谢。我确实运行了100万次以确保没有炸毁堆栈,但让编译器检查了这一点。我添加了它,它给了我一个错误,说它无法优化它,这有点奇怪,因为我本来以为100万次会炸毁堆栈。我的错误是@tailrec a此处的注释;proc调用不是最后一个调用;react是。因此它不能是尾部递归的。根据此线程,堆栈溢出不太可能发生。@thoredge尼斯分析此处。我认为第一个调用不能满足我的需要。客户端发送输入,而参与者本身发送自身状态——但它们永远不会在同一时间被处理ime,所以它不能同时访问状态和输入,这就是问题的关键。另外,我不明白你为什么说它短——它看起来并不比任何东西都短。第二个问题我不关注,而且肯定很复杂。另一个答案中的解决方案没有堆栈溢出问题,并且实现了所需的功能。我很抱歉我不知道你有什么问题。@taotree-我想它工作正常;我把邮箱过满误解为递归闭包生成。我把“两种方式”改为“两种其他方式”。