【发布时间】:2011-04-27 22:17:18
【问题描述】:
在另一种语言中,我用新状态调用了一些东西来维护它,但我不知道如何使用 scala 演员来做到这一点。我的设想是这样的:
def act(state)
react {
case blah => act(doSomething(state, blah))
}
}
【问题讨论】:
在另一种语言中,我用新状态调用了一些东西来维护它,但我不知道如何使用 scala 演员来做到这一点。我的设想是这样的:
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"
}
}
}
好消息是,只要稍加调整,就可以很容易地概括它。
【讨论】:
还有另外两种方法可以在不使用 var 的情况下将状态存储在 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
}
}
或者,如果您需要保存在其他消息期间可访问的状态,您可以创建另一个 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 不是那么轻量级的!),并且它使代码大大复杂化。在大多数情况下,将您的可变状态安全地隐藏为演员内的private[this] var 更为实用,这样您就知道只有演员本身可以更改其可变状态。或者,您可以不使用新的参与者进行回复,而是使用调用者应该传回的状态信息进行回复,但这稍微不安全,因为原则上他们可以修改状态信息,而不仅仅是再次传回。
【讨论】: