在另一種語言中,我有一些自己與新狀態調用來維護它,但我沒有看到如何與scala演員做到這一點。這樣的事情是我如何設想:斯卡拉保持狀態在沒有var的演員
def act(state)
react {
case blah => act(doSomething(state, blah))
}
}
在另一種語言中,我有一些自己與新狀態調用來維護它,但我沒有看到如何與scala演員做到這一點。這樣的事情是我如何設想:斯卡拉保持狀態在沒有var的演員
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"
}
}
}
的好處是多一點的調整,它可以很容易地一概而論。
還有兩種方法可以在不使用變量的情況下在演員中存儲狀態。如果你只需要直傳狀態,可以讓演員將消息發送到本身:
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
更爲實用,以便您知道只有演員本身可以更改其可變狀態。另外,你可以不用新的actor來回答,而是用調用者應該返回的狀態信息來回答,但這樣做的安全性稍差,因爲他們原則上可以修改狀態信息而不是僅僅傳遞回來。
我不認爲第一個做我需要的。客戶端發送輸入,並且主角本身發送自己的狀態 - 但是他們從不被同時處理,所以它不能同時訪問狀態和輸入,這是整個點。另外,我不明白你爲什麼說它更短 - 它不會比任何東西都短。 而第二個我沒有遵循,當然是複雜的。 另一個答案中的解決方案沒有堆棧溢出問題,並且不需要做什麼。我不確定你有什麼問題。 – mentics 2011-04-28 15:46:32
@taotree - 我想它可以正常工作;我誤解了一個溢出郵箱作爲遞歸閉包生成。我已經將「兩種方式」改變爲「兩種其他方式」。 – 2011-04-28 16:45:58
像這樣的情況下,將@tailrec註釋添加到proc方法是明智的(http://stackoverflow.com/questions/3114142/what-is-the-scala-annotation-to-ensure-a-尾遞歸函數-被優化)。確保你不會炸燬你的堆棧。 – thoredge 2011-04-27 22:52:06
謝謝。我確實運行了100萬次,以確保不是,但讓編譯器檢查是否正確。我添加了它,它給了我一個錯誤,說它不能優化它,這有點奇怪,因爲我會盡管有一百萬次會炸掉一個堆棧,否則。 – mentics 2011-04-28 01:19:18
我在這裏錯了@tailrec註釋; proc電話不是最後一個電話;反應是。因此它不能是尾遞歸。根據這個線程http://scala-programming-language.1934581.n4.nabble.com/scala-Tail-recursion-question-td1990627.html堆棧溢出不太可能發生。 – thoredge 2011-04-28 07:50:40