Скала поддерживающая состояние в актерах без вар - PullRequest
3 голосов
/ 28 апреля 2011

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

def act(state)
  react {
    case blah => act(doSomething(state, blah))
  }
}

Ответы [ 2 ]

1 голос
/ 28 апреля 2011

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

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"
    }
  }
}

Приятно то, что при небольшом количестве настроек ее можно довольно легко обобщить.

0 голосов
/ 28 апреля 2011

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

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

...