2014-02-21 3 views
0

Я использую планировщик Akka, чтобы пошатнуть отправку сообщений из списка, созданного из чтения в строках файла. Вот код:Scala: проблема с прямой ссылкой + счетчик циклов

def startClock { 
      val filename = "conf/my_file.json" 
      val lines = scala.io.Source.fromFile(filename).getLines.toList 
      var linePtr = 0 

      if(linePtr == lines.length) { 
      clock.cancel() 
      } 
      else { 
      Logger.info(s"num: $linePtr") 
      default ! Message(lines(linePtr)) 
      linePtr = linePtr + 1 
      } 
     } 

lazy val clock: Cancellable = Akka.system.scheduler.schedule(Duration.Zero, Duration.create(5000, TimeUnit.MILLISECONDS))(startClock) 
val x = clock 

Теперь для того, чтобы обойти эту ошибку вперед ссылка компилятор, который выглядел так: play.PlayExceptions$CompilationException: Compilation error[forward reference extends over definition of value clock]

я должен был установить часы на lazy и затем ссылаться на него на следующей строке чтобы вызвать startClock, и он делает эту часть просто отлично. Вопрос, который у меня есть, linePtr всегда 0. Он никогда не увеличивается, но код в блоке else {} всегда подтверждается. У меня, по сути, есть бесконечная рекурсия, и я недостаточно знаком с Scala, чтобы определить, что я сделал неправильно. Я также попытался определить val clock до startClock, но затем у меня есть прямая ссылка в обратном сценарии. Похоже на проблему с цыпленком и яйцом.

+1

Одна из проблем, которые я вижу, состоит в том, что 'linePtr' определяется как локальный для функции' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' Каждый раз, когда 'startClock' вызывается планировщиком, он всегда устанавливает' linePtr' в 0, поэтому он всегда попадает в ваш оператор else. Если вы хотите правильно увеличивать, вы, вероятно, должны определять 'filename',' lines' и 'linePtr' вне функции' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '. Это был бы грязный код, поскольку он очень «бок эффектный», но это был бы шаг в правильном направлении для того, что вы хотите сделать. – cmbaxter

ответ

4

Возможно, урок не о том, как работает захват переменной, но об использовании API. Начиная с getLines вы получаете итератор, просто используйте его для итерации. Специально:

val lines = Source.fromFile(f).getLines 
val clock = scheduler schedule send 
def send = if (lines.hasNext) d ! Message(lines.next) else clock.cancel() 
Смежные вопросы