Scala 在没有 var 的情况下维持 Actor 的状态

发布于 2024-11-03 10:36:27 字数 175 浏览 0 评论 0原文

在另一种语言中,我有一些东西用新的状态来维护它,但我不知道如何用 scala actor 来做到这一点。我的设想是这样的:

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

In another language, I have had something call itself with the new state to maintain it but I don't see how to do that with scala actors. Something like this is how I would envision this:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

秋叶绚丽 2024-11-10 10:36:27

嗯..有趣的事情。我稍微调整了一下我的问题,发现它可以编译。我意识到所发生的只是我必须返回一个部分函数。好吧,我可以返回一个带有参数的部分函数,​​所以...

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"
    }
  }
}

好的一点是,通过更多的调整,它可以很容易地推广。

Well.. funny thing. I tweak my question a little and find it compiles. I realized that all that happens is that I have to return a partial function. Well I can return a partial function that has a parameter in there, so...

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"
    }
  }
}

The nice thing is that with a little more tweaking, it could be generalized quite easily.

半世晨晓 2024-11-10 10:36:27

还有另外两种方法可以在不使用变量的情况下在参与者中存储状态。如果您只需要向前传递状态,则可以让 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
  }
}

或者,如果您需要保存在其他消息期间可访问的状态,则可以创建另一个 Actor;无论谁给你打电话,都需要了解新演员的情况:

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
  }
}

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

There are two other ways to store state in actors without using vars. If you only need to pass state forward, you can have the actor send a message to itself:

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
  }
}

Alternatively, if you need to save state that is accessible during other messages, you can create another actor; whoever is calling you then needs to be informed about the new actor:

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
  }
}

Personally, I think it's silly to do things this way. It's very inefficient (a new actor has to be created and an old one disposed of any time state changes--and actors are not that lightweight!), and it substantially complicates the code. It's more practical in most cases to keep your mutable state safely hidden as private[this] var within the actor, so that you know that only the actor itself may change its mutable state. Alternatively, you can reply not with a new actor but with state information that the caller is supposed to pass back, but this is slightly less safe since they could, in principle, modify the state information rather than just passing it back again.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文