Исключение Stackoverflow с использованием акторов Scala и receiveWithin - PullRequest
3 голосов
/ 25 мая 2011

Через некоторое время этот актер заполняет стек. Возможные решения?

object Puller extends Actor {

 def act() = {
  receiveWithin(2000) {
    case Stop => println("stoping puller")
        exit()
    case Noop => println("nothing happens")
        act()
    case TIMEOUT => doPull
        act()
  }
}

  def doPull() = // stuff...
}

Мне не нравится этот код в Программировании в Scala.

Ответы [ 2 ]

4 голосов
/ 25 мая 2011

Ваш act не является хвостово-рекурсивным. Вы можете изменить его следующим образом:

  @tailrec // in the presence of this annotation, the compiler will complain, if the code is not tail-recursive
  def act() = {
    receiveWithin(2000) {
      case Stop => println("stoping puller"); exit()
      case Noop => println("nothing happens")
      case TIMEOUT => doPull
    }
    act()
  }
4 голосов
/ 25 мая 2011

Ну, это переполняет стек по очень очевидным причинам; он рекурсивный, но не хвостовой. Здесь есть два варианта:

Либо : использовать цикл while:

def act() = 
  while(true) {
    receiveWithin(2000) {
      case Stop    => println("stoping puller"); exit()
      case Noop    => println("nothing happens")
      case TIMEOUT => doPull
    }
  }

или : используйте loop и react (что дает дополнительное преимущество, заключающееся в возможности масштабирования за счет отделения актора от зацепления одного потока).

def act() = 
  loop {
    reactWithin(2000) {
      case Stop    => println("stoping puller"); exit()
      case Noop    => println("nothing happens")
      case TIMEOUT => doPull
    }
  }

Если этот код существует в Программирование на Scala , он, скорее всего, подразумевает скорее подтверждение концепции, нежели жизнеспособный производственный код. Фактически из памяти объясняется, как можно избежать рекурсивных вызовов act.

...