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.