Есть два других способа сохранения состояния в актерах без использования переменных. Если вам нужно только передать состояние вперед, вы можете попросить актера отправить себе сообщение:
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
внутри субъекта, чтобы вы знали, что только сам субъект может изменить свое изменяемое состояние. В качестве альтернативы вы можете ответить не новым актером, а информацией о состоянии, которую вызывающий абонент должен передать обратно, но это немного менее безопасно, поскольку в принципе они могут изменять информацию о состоянии, а не просто возвращать ее обратно.