Альтернативы использованию "var" для государства с актерами?

Я обнаружил, что довольно часто использую vars с аккскими актерами для поддержания состояния. Например, если я, мой актер, должен поддерживать список элементов, я мог бы сделать что-то вроде:

class ListActor extends Actor{
  var xs : List[Int] = List()

  def receive = {
    case x : Int => xs = x :: xs
  }
}

Использование изменяемой переменной, похоже, противоречит духу Scala. В качестве альтернативы я использовал это:

class ListActor2 extends Actor{
  import context._

  def collect_ints(accu : List[Int]) : Receive = {
    case x : Int => become(collect_ints(x :: accu))
  }

  def receive = collect_ints(Nil)
}

Мне нравится, как это выглядит больше, но мне нужно беспокоиться о переполнении стека?

Я знаю о признаке FSM и использовал это раньше, но для некоторых ситуаций это кажется слишком большим.

Каков рекомендуемый способ поддержания простого состояния? Существуют ли другие альтернативы, о которых я не знаю?

Кроме того, это вообще плохой знак, если мне часто приходится менять переменные переменные? Я не правильно использую модель актера?

Ответы

Ответ 1

Я не вижу проблемы с var для простого состояния в модели актера.

По дизайну Akka предотвращает повреждение или блокировку актера при одновременном доступе к переменным состояния.

Пока вы не показываете свое состояние другим потокам с использованием Будущее, например, использование var для простого состояния не должно быть проблема.

Ответ 2

Существует два варианта метода become: один, который толкает поведение на стек, а другой - нет. Последний является значением по умолчанию, поэтому вам не нужно беспокоиться о том, что стеки поведения становятся слишком большими. Использование become для управления состоянием таким образом является для него вполне допустимым использованием.

Ответ 3

Akka FSM на самом деле очень компактная идиома для поддержания состояния в актерской системе, как в этом примере:

sealed trait State
case object Active extends State

class ListActor extends Actor with FSM[State,List[Int]] {

  startWith(Active,List[Int]())

  when(Active) {
    case Event(x:Int,xs) => stay using x :: xs
  }
}

Используя все альтернативы, обсуждаемые здесь, FSM берет мой голос за все, что является тенью, более сложным, чем тривиальным.