2014-02-21 44 views
0

我正在使用Akka計劃程序來錯開從列表中讀取文件的行中構建的消息的發送。下面是一些代碼:斯卡拉:與前向參考+循環計數器的問題

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並不熟悉,無法確定我在這裏做了什麼錯誤。我也嘗試在startClock之前定義val clock,但是在逆向場景中我也有前向參考。在這裏看起來像雞和雞蛋的問題。

+1

我可以看到一個問題是'linePtr'被定義爲''startClock'函數的本地。每次'startClock'被調度器調用時,它總是將'linePtr'設置爲0,這就是爲什麼它總是碰到你的else語句。如果你想正確地遞增,那麼你可能應該在'startClock'函數之外定義'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()