This code is from akka documentation. It impelements an actor using the recommended functional style:
import akka.actor.typed.Behavior
import akka.actor.typed.scaladsl.ActorContext
import akka.actor.typed.scaladsl.Behaviors
object Counter {
sealed trait Command
case object Increment extends Command
final case class GetValue(replyTo: ActorRef[Value]) extends Command
final case class Value(n: Int)
def apply(): Behavior[Command] =
counter(0)
private def counter(n: Int): Behavior[Command] =
Behaviors.receive { (context, message) =>
message match {
case Increment =>
val newValue = n + 1
context.log.debug("Incremented counter to [{}]", newValue)
counter(newValue)
case GetValue(replyTo) =>
replyTo ! Value(n)
Behaviors.same
}
}
}
The actor contains a recursive call "counter(newValue)" to maintain mutable state by functional means. When I implement this and add the @tailrec annotation to the function, the scala compiler complains as the call is not tail recursive, even it seems to be in the last position. This means, sooner or later a stack overflow exception will occur (imagine you just want to count all incoming messages and there are some billions of them - no java stack would be big enough).
Is it possible to make the call tail recursive or do I have to fallback to the object oriented style with mutable variables to handle those cases?